1 // © 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: UTF-8 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 * Traced Function Exit return types. 52 * Flags indicating the number and types of varargs included in a call 53 * to a UTraceExit function. 54 * Bits 0-3: The function return type. First variable param. 55 * Bit 4: Flag for presence of U_ErrorCode status param. 56 * @internal 57 */ 58 typedef enum UTraceExitVal { 59 /** The traced function returns no value @internal */ 60 UTRACE_EXITV_NONE = 0, 61 /** The traced function returns an int32_t, or compatible, type. @internal */ 62 UTRACE_EXITV_I32 = 1, 63 /** The traced function returns a pointer @internal */ 64 UTRACE_EXITV_PTR = 2, 65 /** The traced function returns a UBool @internal */ 66 UTRACE_EXITV_BOOL = 3, 67 /** Mask to extract the return type values from a UTraceExitVal @internal */ 68 UTRACE_EXITV_MASK = 0xf, 69 /** Bit indicating that the traced function includes a UErrorCode parameter @internal */ 70 UTRACE_EXITV_STATUS = 0x10 71 } UTraceExitVal; 72 73 /** 74 * Trace function for the entry point of a function. 75 * Do not use directly, use UTRACE_ENTRY instead. 76 * @param fnNumber The UTraceFunctionNumber for the current function. 77 * @internal 78 */ 79 U_CAPI void U_EXPORT2 80 utrace_entry(int32_t fnNumber); 81 82 /** 83 * Trace function for each exit point of a function. 84 * Do not use directly, use UTRACE_EXIT* instead. 85 * @param fnNumber The UTraceFunctionNumber for the current function. 86 * @param returnType The type of the value returned by the function. 87 * @param errorCode The UErrorCode value at function exit. See UTRACE_EXIT. 88 * @internal 89 */ 90 U_CAPI void U_EXPORT2 91 utrace_exit(int32_t fnNumber, int32_t returnType, ...); 92 93 94 /** 95 * Trace function used inside functions that have a UTRACE_ENTRY() statement. 96 * Do not use directly, use UTRACE_DATAX() macros instead. 97 * 98 * @param utraceFnNumber The number of the current function, from the local 99 * variable of the same name. 100 * @param level The trace level for this message. 101 * @param fmt The trace format string. 102 * 103 * @internal 104 */ 105 U_CAPI void U_EXPORT2 106 utrace_data(int32_t utraceFnNumber, int32_t level, const char *fmt, ...); 107 108 U_CDECL_END 109 110 #if U_ENABLE_TRACING 111 112 /** 113 * Boolean expression to see if ICU tracing is turned on 114 * to at least the specified level. 115 * @internal 116 */ 117 #define UTRACE_LEVEL(level) (utrace_getLevel()>=(level)) 118 119 /** 120 * Flag bit in utraceFnNumber, the local variable added to each function 121 * with tracing code to contains the function number. 122 * 123 * Set the flag if the function's entry is traced, which will cause the 124 * function's exit to also be traced. utraceFnNumber is uncoditionally 125 * set at entry, whether or not the entry is traced, so that it will 126 * always be available for error trace output. 127 * @internal 128 */ 129 #define UTRACE_TRACED_ENTRY 0x80000000 130 131 /** 132 * Trace statement for the entry point of a function. 133 * Stores the function number in a local variable. 134 * In C code, must be placed immediately after the last variable declaration. 135 * Must be matched with UTRACE_EXIT() at all function exit points. 136 * 137 * Tracing should start with UTRACE_ENTRY after checking for 138 * U_FAILURE at function entry, so that if a function returns immediately 139 * because of a pre-existing error condition, it does not show up in the trace, 140 * consistent with ICU's error handling model. 141 * 142 * @param fnNumber The UTraceFunctionNumber for the current function. 143 * @internal 144 */ 145 #define UTRACE_ENTRY(fnNumber) \ 146 int32_t utraceFnNumber=(fnNumber); \ 147 UPRV_BLOCK_MACRO_BEGIN { \ 148 if(utrace_getLevel()>=UTRACE_INFO) { \ 149 utrace_entry(fnNumber); \ 150 utraceFnNumber |= UTRACE_TRACED_ENTRY; \ 151 } \ 152 } UPRV_BLOCK_MACRO_END 153 154 155 /** 156 * Trace statement for the entry point of open and close functions. 157 * Produces trace output at a less verbose setting than plain UTRACE_ENTRY 158 * Stores the function number in a local variable. 159 * In C code, must be placed immediately after the last variable declaration. 160 * Must be matched with UTRACE_EXIT() at all function exit points. 161 * 162 * @param fnNumber The UTraceFunctionNumber for the current function. 163 * @internal 164 */ 165 #define UTRACE_ENTRY_OC(fnNumber) \ 166 int32_t utraceFnNumber=(fnNumber); \ 167 UPRV_BLOCK_MACRO_BEGIN { \ 168 if(utrace_getLevel()>=UTRACE_OPEN_CLOSE) { \ 169 utrace_entry(fnNumber); \ 170 utraceFnNumber |= UTRACE_TRACED_ENTRY; \ 171 } \ 172 } UPRV_BLOCK_MACRO_END 173 174 /** 175 * Trace statement for each exit point of a function that has a UTRACE_ENTRY() 176 * statement. 177 * 178 * @param errorCode The function's ICU UErrorCode value at function exit, 179 * or U_ZERO_ERROR if the function does not use a UErrorCode. 180 * 0==U_ZERO_ERROR indicates success, 181 * positive values an error (see u_errorName()), 182 * negative values an informational status. 183 * 184 * @internal 185 */ 186 #define UTRACE_EXIT() UPRV_BLOCK_MACRO_BEGIN { \ 187 if(utraceFnNumber & UTRACE_TRACED_ENTRY) { \ 188 utrace_exit(utraceFnNumber & ~UTRACE_TRACED_ENTRY, UTRACE_EXITV_NONE); \ 189 } \ 190 } UPRV_BLOCK_MACRO_END 191 192 /** 193 * Trace statement for each exit point of a function that has a UTRACE_ENTRY() 194 * statement, and that returns a value. 195 * 196 * @param val The function's return value, int32_t or compatible type. 197 * 198 * @internal 199 */ 200 #define UTRACE_EXIT_VALUE(val) UPRV_BLOCK_MACRO_BEGIN { \ 201 if(utraceFnNumber & UTRACE_TRACED_ENTRY) { \ 202 utrace_exit(utraceFnNumber & ~UTRACE_TRACED_ENTRY, UTRACE_EXITV_I32, val); \ 203 } \ 204 } UPRV_BLOCK_MACRO_END 205 206 #define UTRACE_EXIT_STATUS(status) UPRV_BLOCK_MACRO_BEGIN { \ 207 if(utraceFnNumber & UTRACE_TRACED_ENTRY) { \ 208 utrace_exit(utraceFnNumber & ~UTRACE_TRACED_ENTRY, UTRACE_EXITV_STATUS, status); \ 209 } \ 210 } UPRV_BLOCK_MACRO_END 211 212 #define UTRACE_EXIT_VALUE_STATUS(val, status) UPRV_BLOCK_MACRO_BEGIN { \ 213 if(utraceFnNumber & UTRACE_TRACED_ENTRY) { \ 214 utrace_exit(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (UTRACE_EXITV_I32 | UTRACE_EXITV_STATUS), val, status); \ 215 } \ 216 } UPRV_BLOCK_MACRO_END 217 218 #define UTRACE_EXIT_PTR_STATUS(ptr, status) UPRV_BLOCK_MACRO_BEGIN { \ 219 if(utraceFnNumber & UTRACE_TRACED_ENTRY) { \ 220 utrace_exit(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (UTRACE_EXITV_PTR | UTRACE_EXITV_STATUS), ptr, status); \ 221 } \ 222 } UPRV_BLOCK_MACRO_END 223 224 /** 225 * Trace statement used inside functions that have a UTRACE_ENTRY() statement. 226 * Takes no data arguments. 227 * The number of arguments for this macro must match the number of inserts 228 * in the format string. Vector inserts count as two arguments. 229 * Calls utrace_data() if the level is high enough. 230 * @internal 231 */ 232 #define UTRACE_DATA0(level, fmt) UPRV_BLOCK_MACRO_BEGIN { \ 233 if(UTRACE_LEVEL(level)) { \ 234 utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (level), (fmt)); \ 235 } \ 236 } UPRV_BLOCK_MACRO_END 237 238 /** 239 * Trace statement used inside functions that have a UTRACE_ENTRY() statement. 240 * Takes one data argument. 241 * The number of arguments for this macro must match the number of inserts 242 * in the format string. Vector inserts count as two arguments. 243 * Calls utrace_data() if the level is high enough. 244 * @internal 245 */ 246 #define UTRACE_DATA1(level, fmt, a) UPRV_BLOCK_MACRO_BEGIN { \ 247 if(UTRACE_LEVEL(level)) { \ 248 utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY , (level), (fmt), (a)); \ 249 } \ 250 } UPRV_BLOCK_MACRO_END 251 252 /** 253 * Trace statement used inside functions that have a UTRACE_ENTRY() statement. 254 * Takes two data arguments. 255 * The number of arguments for this macro must match the number of inserts 256 * in the format string. Vector inserts count as two arguments. 257 * Calls utrace_data() if the level is high enough. 258 * @internal 259 */ 260 #define UTRACE_DATA2(level, fmt, a, b) UPRV_BLOCK_MACRO_BEGIN { \ 261 if(UTRACE_LEVEL(level)) { \ 262 utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY , (level), (fmt), (a), (b)); \ 263 } \ 264 } UPRV_BLOCK_MACRO_END 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) UPRV_BLOCK_MACRO_BEGIN { \ 275 if(UTRACE_LEVEL(level)) { \ 276 utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (level), (fmt), (a), (b), (c)); \ 277 } \ 278 } UPRV_BLOCK_MACRO_END 279 280 /** 281 * Trace statement used inside functions that have a UTRACE_ENTRY() statement. 282 * Takes four data arguments. 283 * The number of arguments for this macro must match the number of inserts 284 * in the format string. Vector inserts count as two arguments. 285 * Calls utrace_data() if the level is high enough. 286 * @internal 287 */ 288 #define UTRACE_DATA4(level, fmt, a, b, c, d) UPRV_BLOCK_MACRO_BEGIN { \ 289 if(UTRACE_LEVEL(level)) { \ 290 utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (level), (fmt), (a), (b), (c), (d)); \ 291 } \ 292 } UPRV_BLOCK_MACRO_END 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) UPRV_BLOCK_MACRO_BEGIN { \ 303 if(UTRACE_LEVEL(level)) { \ 304 utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (level), (fmt), (a), (b), (c), (d), (e)); \ 305 } \ 306 } UPRV_BLOCK_MACRO_END 307 308 /** 309 * Trace statement used inside functions that have a UTRACE_ENTRY() statement. 310 * Takes six data arguments. 311 * The number of arguments for this macro must match the number of inserts 312 * in the format string. Vector inserts count as two arguments. 313 * Calls utrace_data() if the level is high enough. 314 * @internal 315 */ 316 #define UTRACE_DATA6(level, fmt, a, b, c, d, e, f) UPRV_BLOCK_MACRO_BEGIN { \ 317 if(UTRACE_LEVEL(level)) { \ 318 utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (level), (fmt), (a), (b), (c), (d), (e), (f)); \ 319 } \ 320 } UPRV_BLOCK_MACRO_END 321 322 /** 323 * Trace statement used inside functions that have a UTRACE_ENTRY() statement. 324 * Takes seven data arguments. 325 * The number of arguments for this macro must match the number of inserts 326 * in the format string. Vector inserts count as two arguments. 327 * Calls utrace_data() if the level is high enough. 328 * @internal 329 */ 330 #define UTRACE_DATA7(level, fmt, a, b, c, d, e, f, g) UPRV_BLOCK_MACRO_BEGIN { \ 331 if(UTRACE_LEVEL(level)) { \ 332 utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (level), (fmt), (a), (b), (c), (d), (e), (f), (g)); \ 333 } \ 334 } UPRV_BLOCK_MACRO_END 335 336 /** 337 * Trace statement used inside functions that have a UTRACE_ENTRY() statement. 338 * Takes eight data arguments. 339 * The number of arguments for this macro must match the number of inserts 340 * in the format string. Vector inserts count as two arguments. 341 * Calls utrace_data() if the level is high enough. 342 * @internal 343 */ 344 #define UTRACE_DATA8(level, fmt, a, b, c, d, e, f, g, h) UPRV_BLOCK_MACRO_BEGIN { \ 345 if(UTRACE_LEVEL(level)) { \ 346 utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (level), (fmt), (a), (b), (c), (d), (e), (f), (g), (h)); \ 347 } \ 348 } UPRV_BLOCK_MACRO_END 349 350 /** 351 * Trace statement used inside functions that have a UTRACE_ENTRY() statement. 352 * Takes nine data arguments. 353 * The number of arguments for this macro must match the number of inserts 354 * in the format string. Vector inserts count as two arguments. 355 * Calls utrace_data() if the level is high enough. 356 * @internal 357 */ 358 #define UTRACE_DATA9(level, fmt, a, b, c, d, e, f, g, h, i) UPRV_BLOCK_MACRO_BEGIN { \ 359 if(UTRACE_LEVEL(level)) { \ 360 utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (level), (fmt), (a), (b), (c), (d), (e), (f), (g), (h), (i)); \ 361 } \ 362 } UPRV_BLOCK_MACRO_END 363 364 #else 365 366 /* 367 * When tracing is disabled, the following macros become empty 368 */ 369 370 #define UTRACE_LEVEL(level) 0 371 #define UTRACE_ENTRY(fnNumber) 372 #define UTRACE_ENTRY_OC(fnNumber) 373 #define UTRACE_EXIT() 374 #define UTRACE_EXIT_VALUE(val) 375 #define UTRACE_EXIT_STATUS(status) 376 #define UTRACE_EXIT_VALUE_STATUS(val, status) 377 #define UTRACE_EXIT_PTR_STATUS(ptr, status) 378 #define UTRACE_DATA0(level, fmt) 379 #define UTRACE_DATA1(level, fmt, a) 380 #define UTRACE_DATA2(level, fmt, a, b) 381 #define UTRACE_DATA3(level, fmt, a, b, c) 382 #define UTRACE_DATA4(level, fmt, a, b, c, d) 383 #define UTRACE_DATA5(level, fmt, a, b, c, d, e) 384 #define UTRACE_DATA6(level, fmt, a, b, c, d, e, f) 385 #define UTRACE_DATA7(level, fmt, a, b, c, d, e, f, g) 386 #define UTRACE_DATA8(level, fmt, a, b, c, d, e, f, g, h) 387 #define UTRACE_DATA9(level, fmt, a, b, c, d, e, f, g, h, i) 388 389 #endif 390 391 #endif 392