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 if(utrace_getLevel()>=UTRACE_INFO) { \ 148 utrace_entry(fnNumber); \ 149 utraceFnNumber |= UTRACE_TRACED_ENTRY; \ 150 } 151 152 153 /** 154 * Trace statement for the entry point of open and close functions. 155 * Produces trace output at a less verbose setting than plain UTRACE_ENTRY 156 * Stores the function number in a local variable. 157 * In C code, must be placed immediately after the last variable declaration. 158 * Must be matched with UTRACE_EXIT() at all function exit points. 159 * 160 * @param fnNumber The UTraceFunctionNumber for the current function. 161 * @internal 162 */ 163 #define UTRACE_ENTRY_OC(fnNumber) \ 164 int32_t utraceFnNumber=(fnNumber); \ 165 if(utrace_getLevel()>=UTRACE_OPEN_CLOSE) { \ 166 utrace_entry(fnNumber); \ 167 utraceFnNumber |= UTRACE_TRACED_ENTRY; \ 168 } 169 170 /** 171 * Trace statement for each exit point of a function that has a UTRACE_ENTRY() 172 * statement. 173 * 174 * @param errorCode The function's ICU UErrorCode value at function exit, 175 * or U_ZERO_ERROR if the function does not use a UErrorCode. 176 * 0==U_ZERO_ERROR indicates success, 177 * positive values an error (see u_errorName()), 178 * negative values an informational status. 179 * 180 * @internal 181 */ 182 #define UTRACE_EXIT() \ 183 {if(utraceFnNumber & UTRACE_TRACED_ENTRY) { \ 184 utrace_exit(utraceFnNumber & ~UTRACE_TRACED_ENTRY, UTRACE_EXITV_NONE); \ 185 }} 186 187 /** 188 * Trace statement for each exit point of a function that has a UTRACE_ENTRY() 189 * statement, and that returns a value. 190 * 191 * @param val The function's return value, int32_t or comatible type. 192 * 193 * @internal 194 */ 195 #define UTRACE_EXIT_VALUE(val) \ 196 {if(utraceFnNumber & UTRACE_TRACED_ENTRY) { \ 197 utrace_exit(utraceFnNumber & ~UTRACE_TRACED_ENTRY, UTRACE_EXITV_I32, val); \ 198 }} 199 200 #define UTRACE_EXIT_STATUS(status) \ 201 {if(utraceFnNumber & UTRACE_TRACED_ENTRY) { \ 202 utrace_exit(utraceFnNumber & ~UTRACE_TRACED_ENTRY, UTRACE_EXITV_STATUS, status); \ 203 }} 204 205 #define UTRACE_EXIT_VALUE_STATUS(val, status) \ 206 {if(utraceFnNumber & UTRACE_TRACED_ENTRY) { \ 207 utrace_exit(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (UTRACE_EXITV_I32 | UTRACE_EXITV_STATUS), val, status); \ 208 }} 209 210 #define UTRACE_EXIT_PTR_STATUS(ptr, status) \ 211 {if(utraceFnNumber & UTRACE_TRACED_ENTRY) { \ 212 utrace_exit(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (UTRACE_EXITV_PTR | UTRACE_EXITV_STATUS), ptr, status); \ 213 }} 214 215 /** 216 * Trace statement used inside functions that have a UTRACE_ENTRY() statement. 217 * Takes no data arguments. 218 * The number of arguments for this macro must match the number of inserts 219 * in the format string. Vector inserts count as two arguments. 220 * Calls utrace_data() if the level is high enough. 221 * @internal 222 */ 223 #define UTRACE_DATA0(level, fmt) \ 224 if(UTRACE_LEVEL(level)) { \ 225 utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (level), (fmt)); \ 226 } 227 228 /** 229 * Trace statement used inside functions that have a UTRACE_ENTRY() statement. 230 * Takes one data argument. 231 * The number of arguments for this macro must match the number of inserts 232 * in the format string. Vector inserts count as two arguments. 233 * Calls utrace_data() if the level is high enough. 234 * @internal 235 */ 236 #define UTRACE_DATA1(level, fmt, a) \ 237 if(UTRACE_LEVEL(level)) { \ 238 utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY , (level), (fmt), (a)); \ 239 } 240 241 /** 242 * Trace statement used inside functions that have a UTRACE_ENTRY() statement. 243 * Takes two data arguments. 244 * The number of arguments for this macro must match the number of inserts 245 * in the format string. Vector inserts count as two arguments. 246 * Calls utrace_data() if the level is high enough. 247 * @internal 248 */ 249 #define UTRACE_DATA2(level, fmt, a, b) \ 250 if(UTRACE_LEVEL(level)) { \ 251 utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY , (level), (fmt), (a), (b)); \ 252 } 253 254 /** 255 * Trace statement used inside functions that have a UTRACE_ENTRY() statement. 256 * Takes three data arguments. 257 * The number of arguments for this macro must match the number of inserts 258 * in the format string. Vector inserts count as two arguments. 259 * Calls utrace_data() if the level is high enough. 260 * @internal 261 */ 262 #define UTRACE_DATA3(level, fmt, a, b, c) \ 263 if(UTRACE_LEVEL(level)) { \ 264 utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (level), (fmt), (a), (b), (c)); \ 265 } 266 267 /** 268 * Trace statement used inside functions that have a UTRACE_ENTRY() statement. 269 * Takes four data arguments. 270 * The number of arguments for this macro must match the number of inserts 271 * in the format string. Vector inserts count as two arguments. 272 * Calls utrace_data() if the level is high enough. 273 * @internal 274 */ 275 #define UTRACE_DATA4(level, fmt, a, b, c, d) \ 276 if(UTRACE_LEVEL(level)) { \ 277 utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (level), (fmt), (a), (b), (c), (d)); \ 278 } 279 280 /** 281 * Trace statement used inside functions that have a UTRACE_ENTRY() statement. 282 * Takes five 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_DATA5(level, fmt, a, b, c, d, e) \ 289 if(UTRACE_LEVEL(level)) { \ 290 utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (level), (fmt), (a), (b), (c), (d), (e)); \ 291 } 292 293 /** 294 * Trace statement used inside functions that have a UTRACE_ENTRY() statement. 295 * Takes six data arguments. 296 * The number of arguments for this macro must match the number of inserts 297 * in the format string. Vector inserts count as two arguments. 298 * Calls utrace_data() if the level is high enough. 299 * @internal 300 */ 301 #define UTRACE_DATA6(level, fmt, a, b, c, d, e, f) \ 302 if(UTRACE_LEVEL(level)) { \ 303 utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (level), (fmt), (a), (b), (c), (d), (e), (f)); \ 304 } 305 306 /** 307 * Trace statement used inside functions that have a UTRACE_ENTRY() statement. 308 * Takes seven data arguments. 309 * The number of arguments for this macro must match the number of inserts 310 * in the format string. Vector inserts count as two arguments. 311 * Calls utrace_data() if the level is high enough. 312 * @internal 313 */ 314 #define UTRACE_DATA7(level, fmt, a, b, c, d, e, f, g) \ 315 if(UTRACE_LEVEL(level)) { \ 316 utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (level), (fmt), (a), (b), (c), (d), (e), (f), (g)); \ 317 } 318 319 /** 320 * Trace statement used inside functions that have a UTRACE_ENTRY() statement. 321 * Takes eight data arguments. 322 * The number of arguments for this macro must match the number of inserts 323 * in the format string. Vector inserts count as two arguments. 324 * Calls utrace_data() if the level is high enough. 325 * @internal 326 */ 327 #define UTRACE_DATA8(level, fmt, a, b, c, d, e, f, g, h) \ 328 if(UTRACE_LEVEL(level)) { \ 329 utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (level), (fmt), (a), (b), (c), (d), (e), (f), (g), (h)); \ 330 } 331 332 /** 333 * Trace statement used inside functions that have a UTRACE_ENTRY() statement. 334 * Takes nine data arguments. 335 * The number of arguments for this macro must match the number of inserts 336 * in the format string. Vector inserts count as two arguments. 337 * Calls utrace_data() if the level is high enough. 338 * @internal 339 */ 340 #define UTRACE_DATA9(level, fmt, a, b, c, d, e, f, g, h, i) \ 341 if(UTRACE_LEVEL(level)) { \ 342 utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (level), (fmt), (a), (b), (c), (d), (e), (f), (g), (h), (i)); \ 343 } 344 345 #else 346 347 /* 348 * When tracing is disabled, the following macros become empty 349 */ 350 351 #define UTRACE_LEVEL(level) 0 352 #define UTRACE_ENTRY(fnNumber) 353 #define UTRACE_ENTRY_OC(fnNumber) 354 #define UTRACE_EXIT() 355 #define UTRACE_EXIT_VALUE(val) 356 #define UTRACE_EXIT_STATUS(status) 357 #define UTRACE_EXIT_VALUE_STATUS(val, status) 358 #define UTRACE_EXIT_PTR_STATUS(ptr, status) 359 #define UTRACE_DATA0(level, fmt) 360 #define UTRACE_DATA1(level, fmt, a) 361 #define UTRACE_DATA2(level, fmt, a, b) 362 #define UTRACE_DATA3(level, fmt, a, b, c) 363 #define UTRACE_DATA4(level, fmt, a, b, c, d) 364 #define UTRACE_DATA5(level, fmt, a, b, c, d, e) 365 #define UTRACE_DATA6(level, fmt, a, b, c, d, e, f) 366 #define UTRACE_DATA7(level, fmt, a, b, c, d, e, f, g) 367 #define UTRACE_DATA8(level, fmt, a, b, c, d, e, f, g, h) 368 #define UTRACE_DATA9(level, fmt, a, b, c, d, e, f, g, h, i) 369 370 #endif 371 372 #endif 373