• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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