|
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 |