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