VirtualBox

root/trunk/include/iprt/log.h

Revision 13832, 54.9 kB (checked in by vboxsync, 2 months ago)

IN_GC -> IN_RC.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /** @file
2  * IPRT - Logging.
3  */
4
5 /*
6  * Copyright (C) 2006-2007 Sun Microsystems, Inc.
7  *
8  * This file is part of VirtualBox Open Source Edition (OSE), as
9  * available from http://www.virtualbox.org. This file is free software;
10  * you can redistribute it and/or modify it under the terms of the GNU
11  * General Public License (GPL) as published by the Free Software
12  * Foundation, in version 2 as it comes in the "COPYING" file of the
13  * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14  * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15  *
16  * The contents of this file may alternatively be used under the terms
17  * of the Common Development and Distribution License Version 1.0
18  * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
19  * VirtualBox OSE distribution, in which case the provisions of the
20  * CDDL are applicable instead of those of the GPL.
21  *
22  * You may elect to license modified versions of this file under the
23  * terms and conditions of either the GPL or the CDDL or both.
24  *
25  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
26  * Clara, CA 95054 USA or visit http://www.sun.com if you need
27  * additional information or have any questions.
28  */
29
30 #ifndef ___iprt_log_h
31 #define ___iprt_log_h
32
33 #include <iprt/cdefs.h>
34 #include <iprt/types.h>
35 #include <iprt/stdarg.h>
36
37 __BEGIN_DECLS
38
39 /** @defgroup grp_rt_log    RTLog - Logging
40  * @ingroup grp_rt
41  * @{
42  */
43
44 /**
45  * IPRT Logging Groups.
46  * (Remember to update RT_LOGGROUP_NAMES!)
47  *
48  * @remark It should be pretty obvious, but just to have
49  *         mentioned it, the values are sorted alphabetically (using the
50  *         english alphabet) except for _DEFAULT which is always first.
51  *
52  *         If anyone might be wondering what the alphabet looks like:
53  *              a b c d e f g h i j k l m n o p q r s t u v w x y z
54  */
55 typedef enum RTLOGGROUP
56 {
57     /** Default logging group. */
58     RTLOGGROUP_DEFAULT,
59     RTLOGGROUP_DIR,
60     RTLOGGROUP_FILE,
61     RTLOGGROUP_FS,
62     RTLOGGROUP_LDR,
63     RTLOGGROUP_PATH,
64     RTLOGGROUP_PROCESS,
65     RTLOGGROUP_THREAD,
66     RTLOGGROUP_TIME,
67     RTLOGGROUP_TIMER,
68     RTLOGGROUP_ZIP = 31,
69     RTLOGGROUP_FIRST_USER = 32
70 } RTLOGGROUP;
71
72 /** @def RT_LOGGROUP_NAMES
73  * IPRT Logging group names.
74  *
75  * Must correspond 100% to RTLOGGROUP!
76  * Don't forget commas!
77  *
78  * @remark It should be pretty obvious, but just to have
79  *         mentioned it, the values are sorted alphabetically (using the
80  *         english alphabet) except for _DEFAULT which is always first.
81  *
82  *         If anyone might be wondering what the alphabet looks like:
83  *              a b c d e f g h i j k l m n o p q r s t u v w x y z
84  */
85 #define RT_LOGGROUP_NAMES \
86     "DEFAULT",      \
87     "RT_DIR",       \
88     "RT_FILE",      \
89     "RT_FS",        \
90     "RT_LDR",       \
91     "RT_PATH",      \
92     "RT_PROCESS",   \
93     "RT_THREAD",    \
94     "RT_TIME",      \
95     "RT_TIMER",     \
96     "RT_10", \
97     "RT_11", \
98     "RT_12", \
99     "RT_13", \
100     "RT_14", \
101     "RT_15", \
102     "RT_16", \
103     "RT_17", \
104     "RT_18", \
105     "RT_19", \
106     "RT_20", \
107     "RT_21", \
108     "RT_22", \
109     "RT_23", \
110     "RT_24", \
111     "RT_25", \
112     "RT_26", \
113     "RT_27", \
114     "RT_28", \
115     "RT_29", \
116     "RT_30", \
117     "RT_ZIP"  \
118
119
120 /** @def LOG_GROUP
121  * Active logging group.
122  */
123 #ifndef LOG_GROUP
124 # define LOG_GROUP          RTLOGGROUP_DEFAULT
125 #endif
126
127 /** @def LOG_INSTANCE
128  * Active logging instance.
129  */
130 #ifndef LOG_INSTANCE
131 # define LOG_INSTANCE       NULL
132 #endif
133
134 /** @def LOG_REL_INSTANCE
135  * Active release logging instance.
136  */
137 #ifndef LOG_REL_INSTANCE
138 # define LOG_REL_INSTANCE   NULL
139 #endif
140
141 /** @def LOG_FN_FMT
142  * You can use this to specify you desired way of printing __PRETTY_FUNCTION__
143  * if you dislike the default one.
144  */
145 #ifndef LOG_FN_FMT
146 # define LOG_FN_FMT "%Rfn"
147 #endif
148
149 /** Logger structure. */
150 #ifdef IN_RC
151 typedef struct RTLOGGERRC RTLOGGER;
152 #else
153 typedef struct RTLOGGER RTLOGGER;
154 #endif
155 /** Pointer to logger structure. */
156 typedef RTLOGGER *PRTLOGGER;
157 /** Pointer to const logger structure. */
158 typedef const RTLOGGER *PCRTLOGGER;
159
160
161 /** Guest context logger structure. */
162 typedef struct RTLOGGERRC RTLOGGERRC;
163 /** Pointer to guest context logger structure. */
164 typedef RTLOGGERRC *PRTLOGGERRC;
165 /** Pointer to const guest context logger structure. */
166 typedef const RTLOGGERRC *PCRTLOGGERRC;
167
168
169 /**
170  * Logger function.
171  *
172  * @param   pszFormat   Format string.
173  * @param   ...         Optional arguments as specified in the format string.
174  */
175 typedef DECLCALLBACK(void) FNRTLOGGER(const char *pszFormat, ...);
176 /** Pointer to logger function. */
177 typedef FNRTLOGGER *PFNRTLOGGER;
178
179 /**
180  * Flush function.
181  *
182  * @param   pLogger     Pointer to the logger instance which is to be flushed.
183  */
184 typedef DECLCALLBACK(void) FNRTLOGFLUSH(PRTLOGGER pLogger);
185 /** Pointer to logger function. */
186 typedef FNRTLOGFLUSH *PFNRTLOGFLUSH;
187
188 /**
189  * Flush function.
190  *
191  * @param   pLogger     Pointer to the logger instance which is to be flushed.
192  */
193 typedef DECLCALLBACK(void) FNRTLOGFLUSHGC(PRTLOGGERRC pLogger);
194 /** Pointer to logger function. */
195 typedef RCPTRTYPE(FNRTLOGFLUSHGC *) PFNRTLOGFLUSHGC;
196
197
198 /**
199  * Logger instance structure for GC.
200  */
201 struct RTLOGGERRC
202 {
203     /** Pointer to temporary scratch buffer.
204      * This is used to format the log messages. */
205     char                    achScratch[16384];
206     /** Current scratch buffer position. */
207     RTUINT                  offScratch;
208     /** This is set if a prefix is pending. */
209     RTUINT                  fPendingPrefix;
210     /** Pointer to the logger function.
211      * This is actually pointer to a wrapper which will push a pointer to the
212      * instance pointer onto the stack before jumping to the real logger function.
213      * A very unfortunate hack to work around the missing variadic macro support in C++. */
214     RCPTRTYPE(PFNRTLOGGER)  pfnLogger;
215     /** Pointer to the flush function. */
216     PFNRTLOGFLUSHGC         pfnFlush;
217     /** Magic number (RTLOGGERRC_MAGIC). */
218     uint32_t                u32Magic;
219     /** Logger instance flags - RTLOGFLAGS. */
220     RTUINT                  fFlags;
221     /** Number of groups in the afGroups member. */
222     RTUINT                  cGroups;
223     /** Group flags array - RTLOGGRPFLAGS.
224      * This member have variable length and may extend way beyond
225      * the declared size of 1 entry. */
226     RTUINT                  afGroups[1];
227 };
228
229 /** RTLOGGERRC::u32Magic value. (John Rogers Searle) */
230 #define RTLOGGERRC_MAGIC    0x19320731
231
232
233
234 #ifndef IN_RC
235 /**
236  * Logger instance structure.
237  */
238 struct RTLOGGER
239 {
240     /** Pointer to temporary scratch buffer.
241      * This is used to format the log messages. */
242     char                    achScratch[16384];
243     /** Current scratch buffer position. */
244     RTUINT                  offScratch;
245     /** This is set if a prefix is pending. */
246     RTUINT                  fPendingPrefix;
247     /** Pointer to the logger function.
248      * This is actually pointer to a wrapper which will push a pointer to the
249      * instance pointer onto the stack before jumping to the real logger function.
250      * A very unfortunate hack to work around the missing variadic macro support in C++.
251      * (The memory is (not R0) allocated using RTMemExecAlloc().) */
252     PFNRTLOGGER             pfnLogger;
253     /** Pointer to the flush function. */
254     PFNRTLOGFLUSH           pfnFlush;
255     /** Mutex. */
256     RTSEMFASTMUTEX          MutexSem;
257     /** Magic number. */
258     uint32_t                u32Magic;
259     /** Logger instance flags - RTLOGFLAGS. */
260     RTUINT                  fFlags;
261     /** Destination flags - RTLOGDEST. */
262     RTUINT                  fDestFlags;
263     /** Handle to log file (if open). */
264     RTFILE                  File;
265     /** Pointer to filename.
266      * (The memory is allocated in the smae block as RTLOGGER.) */
267     char                   *pszFilename;
268     /** Pointer to the group name array.
269      * (The data is readonly and provided by the user.) */
270     const char * const     *papszGroups;
271     /** The max number of groups that there is room for in afGroups and papszGroups.
272      * Used by RTLogCopyGroupAndFlags(). */
273     RTUINT                  cMaxGroups;
274     /** Number of groups in the afGroups and papszGroups members. */
275     RTUINT                  cGroups;
276     /** Group flags array - RTLOGGRPFLAGS.
277      * This member have variable length and may extend way beyond
278      * the declared size of 1 entry. */
279     RTUINT                  afGroups[1];
280 };
281
282 /** RTLOGGER::u32Magic value. (Avram Noam Chomsky) */
283 #define RTLOGGER_MAGIC      0x19281207
284
285 #endif
286
287
288 /**
289  * Logger flags.
290  */
291 typedef enum RTLOGFLAGS
292 {
293     /** The logger instance is disabled for normal output. */
294     RTLOGFLAGS_DISABLED             = 0x00000001,
295     /** The logger instance is using buffered output. */
296     RTLOGFLAGS_BUFFERED             = 0x00000002,
297     /** The logger instance expands LF to CR/LF. */
298     RTLOGFLAGS_USECRLF              = 0x00000010,
299     /** Append to the log destination where applicable. */
300     RTLOGFLAGS_APPEND               = 0x00000020,
301     /** Show relative timestamps with PREFIX_TSC and PREFIX_TS */
302     RTLOGFLAGS_REL_TS               = 0x00000040,
303     /** Show decimal timestamps with PREFIX_TSC and PREFIX_TS */
304     RTLOGFLAGS_DECIMAL_TS           = 0x00000080,
305     /** New lines should be prefixed with the write and read lock counts. */
306     RTLOGFLAGS_PREFIX_LOCK_COUNTS   = 0x00008000,
307     /** New lines should be prefixed with the CPU id (ApicID on intel/amd). */
308     RTLOGFLAGS_PREFIX_CPUID         = 0x00010000,
309     /** New lines should be prefixed with the native process id. */
310     RTLOGFLAGS_PREFIX_PID           = 0x00020000,
311     /** New lines should be prefixed with group flag number causing the output. */
312     RTLOGFLAGS_PREFIX_FLAG_NO       = 0x00040000,
313     /** New lines should be prefixed with group flag name causing the output. */
314     RTLOGFLAGS_PREFIX_FLAG          = 0x00080000,
315     /** New lines should be prefixed with group number. */
316     RTLOGFLAGS_PREFIX_GROUP_NO      = 0x00100000,
317     /** New lines should be prefixed with group name. */
318     RTLOGFLAGS_PREFIX_GROUP         = 0x00200000,
319     /** New lines should be prefixed with the native thread id. */
320     RTLOGFLAGS_PREFIX_TID           = 0x00400000,
321     /** New lines should be prefixed with thread name. */
322     RTLOGFLAGS_PREFIX_THREAD        = 0x00800000,
323     /** New lines should be prefixed with formatted timestamp since program start. */
324     RTLOGFLAGS_PREFIX_TIME_PROG     = 0x04000000,
325     /** New lines should be prefixed with formatted timestamp (UCT). */
326     RTLOGFLAGS_PREFIX_TIME          = 0x08000000,
327     /** New lines should be prefixed with milliseconds since program start. */
328     RTLOGFLAGS_PREFIX_MS_PROG       = 0x10000000,
329     /** New lines should be prefixed with timestamp. */
330     RTLOGFLAGS_PREFIX_TSC           = 0x20000000,
331     /** New lines should be prefixed with timestamp. */
332     RTLOGFLAGS_PREFIX_TS            = 0x40000000,
333     /** The prefix mask. */
334     RTLOGFLAGS_PREFIX_MASK          = 0x7cff8000
335 } RTLOGFLAGS;
336
337 /**
338  * Logger per group flags.
339  */
340 typedef enum RTLOGGRPFLAGS
341 {
342     /** Enabled. */
343     RTLOGGRPFLAGS_ENABLED      = 0x00000001,
344     /** Level 1 logging. */
345     RTLOGGRPFLAGS_LEVEL_1      = 0x00000002,
346     /** Level 2 logging. */
347     RTLOGGRPFLAGS_LEVEL_2      = 0x00000004,
348     /** Level 3 logging. */
349     RTLOGGRPFLAGS_LEVEL_3      = 0x00000008,
350     /** Level 4 logging. */
351     RTLOGGRPFLAGS_LEVEL_4      = 0x00000010,
352     /** Level 5 logging. */
353     RTLOGGRPFLAGS_LEVEL_5      = 0x00000020,
354     /** Level 6 logging. */
355     RTLOGGRPFLAGS_LEVEL_6      = 0x00000040,
356     /** Flow logging. */
357     RTLOGGRPFLAGS_FLOW         = 0x00000080,
358
359     /** Lelik logging. */
360     RTLOGGRPFLAGS_LELIK        = 0x00000100,
361     /** Michael logging. */
362     RTLOGGRPFLAGS_MICHAEL      = 0x00000200,
363     /** dmik logging. */
364     RTLOGGRPFLAGS_DMIK         = 0x00000400,
365     /** sunlover logging. */
366     RTLOGGRPFLAGS_SUNLOVER     = 0x00000800,
367     /** Achim logging. */
368     RTLOGGRPFLAGS_ACHIM        = 0x00001000,
369     /** Sander logging. */
370     RTLOGGRPFLAGS_SANDER       = 0x00002000,
371     /** Klaus logging. */
372     RTLOGGRPFLAGS_KLAUS        = 0x00004000,
373     /** Frank logging. */
374     RTLOGGRPFLAGS_FRANK        = 0x00008000,
375     /** bird logging. */
376     RTLOGGRPFLAGS_BIRD         = 0x00010000,
377     /** aleksey logging. */
378     RTLOGGRPFLAGS_ALEKSEY      = 0x00020000,
379     /** NoName logging. */
380     RTLOGGRPFLAGS_NONAME       = 0x00040000
381 } RTLOGGRPFLAGS;
382
383 /**
384  * Logger destination type.
385  */
386 typedef enum RTLOGDEST
387 {
388     /** Log to file. */
389     RTLOGDEST_FILE          = 0x00000001,
390     /** Log to stdout. */
391     RTLOGDEST_STDOUT        = 0x00000002,
392     /** Log to stderr. */
393     RTLOGDEST_STDERR        = 0x00000004,
394     /** Log to debugger (win32 only). */
395     RTLOGDEST_DEBUGGER      = 0x00000008,
396     /** Log to com port. */
397     RTLOGDEST_COM           = 0x00000010,
398     /** Just a dummy flag to be used when no other flag applies. */
399     RTLOGDEST_DUMMY         = 0x20000000,
400     /** Log to a user defined output stream. */
401     RTLOGDEST_USER          = 0x40000000
402 } RTLOGDEST;
403
404
405 RTDECL(void) RTLogPrintfEx(void *pvInstance, unsigned fFlags, unsigned iGroup, const char *pszFormat, ...);
406
407
408 #ifdef DOXYGEN_RUNNING
409 # define LOG_DISABLED
410 # define LOG_ENABLED
411 # define LOG_ENABLE_FLOW
412 #endif
413
414 /** @def LOG_DISABLED
415  * Use this compile time define to disable all logging macros. It can
416  * be overriden for each of the logging macros by the LOG_ENABLE*
417  * compile time defines.
418  */
419
420 /** @def LOG_ENABLED
421  * Use this compile time define to enable logging when not in debug mode
422  * or LOG_DISABLED is set.
423  * This will enabled Log() only.
424  */
425
426 /** @def LOG_ENABLE_FLOW
427  * Use this compile time define to enable flow logging when not in
428  * debug mode or LOG_DISABLED is defined.
429  * This will enable LogFlow() only.
430  */
431
432 /*
433  * Determin whether logging is enabled and forcefully normalize the indicators.
434  */
435 #if (defined(DEBUG) || defined(LOG_ENABLED)) && !defined(LOG_DISABLED)
436 # undef  LOG_DISABLED
437 # undef  LOG_ENABLED
438 # define LOG_ENABLED
439 #else
440 # undef  LOG_ENABLED
441 # undef  LOG_DISABLED
442 # define LOG_DISABLED
443 #endif
444
445
446 /** @def LOG_USE_C99
447  * Governs the use of variadic macros.
448  */
449 #ifndef LOG_USE_C99
450 # if defined(RT_ARCH_AMD64)
451 define LOG_USE_C99
452 # endif
453 #endif
454
455
456 /** @def LogIt
457  * Write to specific logger if group enabled.
458  */
459 #ifdef LOG_ENABLED
460 # if defined(LOG_USE_C99)
461 define _LogRemoveParentheseis(...)                   __VA_ARGS__
462 define _LogIt(pvInst, fFlags, iGroup, ...)           RTLogLoggerEx((PRTLOGGER)pvInst, fFlags, iGroup, __VA_ARGS__)
463 define LogIt(pvInst, fFlags, iGroup, fmtargs)        _LogIt(pvInst, fFlags, iGroup, _LogRemoveParentheseis fmtargs)
464 define _LogItAlways(pvInst, fFlags, iGroup, ...)     RTLogLoggerEx((PRTLOGGER)pvInst, fFlags, ~0U, __VA_ARGS__)
465 define LogItAlways(pvInst, fFlags, iGroup, fmtargs)  _LogItAlways(pvInst, fFlags, iGroup, _LogRemoveParentheseis fmtargs)
466         /** @todo invent a flag or something for skipping the group check so we can pass iGroup. LogItAlways. */
467 # else
468 define LogIt(pvInst, fFlags, iGroup, fmtargs) \
469     do \
470     { \
471         register PRTLOGGER LogIt_pLogger = (PRTLOGGER)(pvInst) ? (PRTLOGGER)(pvInst) : RTLogDefaultInstance(); \
472         if (LogIt_pLogger) \
473         { \
474             register unsigned LogIt_fFlags = LogIt_pLogger->afGroups[(unsigned)(iGroup) < LogIt_pLogger->cGroups ? (unsigned)(iGroup) : 0]; \
475             if ((LogIt_fFlags & ((fFlags) | RTLOGGRPFLAGS_ENABLED)) == ((fFlags) | RTLOGGRPFLAGS_ENABLED)) \
476                 LogIt_pLogger->pfnLogger fmtargs; \
477         } \
478     } while (0)
479 define LogItAlways(pvInst, fFlags, iGroup, fmtargs) \
480     do \
481     { \
482         register PRTLOGGER LogIt_pLogger = (PRTLOGGER)(pvInst) ? (PRTLOGGER)(pvInst) : RTLogDefaultInstance(); \
483         if (LogIt_pLogger) \
484             LogIt_pLogger->pfnLogger fmtargs; \
485     } while (0)
486 # endif
487 #else
488 # define LogIt(pvInst, fFlags, iGroup, fmtargs)         do { } while (0)
489 # define LogItAlways(pvInst, fFlags, iGroup, fmtargs)   do { } while (0)
490 # if defined(LOG_USE_C99)
491 define _LogRemoveParentheseis(...)                   __VA_ARGS__
492 define _LogIt(pvInst, fFlags, iGroup, ...)           do { } while (0)
493 define _LogItAlways(pvInst, fFlags, iGroup, ...)     do { } while (0)
494 # endif
495 #endif
496
497
498 /** @def Log
499  * Level 1 logging that works regardless of the group settings.
500  */
501 #define LogAlways(a)    LogItAlways(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_1, LOG_GROUP, a)
502
503 /** @def Log
504  * Level 1 logging.
505  */
506 #define Log(a)          LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_1, LOG_GROUP, a)
507
508 /** @def Log2
509  * Level 2 logging.
510  */
511 #define Log2(a)         LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_2,  LOG_GROUP, a)
512
513 /** @def Log3
514  * Level 3 logging.
515  */
516 #define Log3(a)         LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_3,  LOG_GROUP, a)
517
518 /** @def Log4
519  * Level 4 logging.
520  */
521 #define Log4(a)         LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_4,  LOG_GROUP, a)
522
523 /** @def Log5
524  * Level 5 logging.
525  */
526 #define Log5(a)         LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_5,  LOG_GROUP, a)
527
528 /** @def Log6
529  * Level 6 logging.
530  */
531 #define Log6(a)         LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_6,  LOG_GROUP, a)
532
533 /** @def LogFlow
534  * Logging of execution flow.
535  */
536 #define LogFlow(a)      LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_FLOW,     LOG_GROUP, a)
537
538 /** @def LogLelik
539  *  lelik logging.
540  */
541 #define LogLelik(a)     LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_LELIK,    LOG_GROUP, a)
542
543
544 /** @def LogMichael
545  * michael logging.
546  */
547 #define LogMichael(a)   LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_MICHAEL,  LOG_GROUP, a)
548
549 /** @def LogDmik
550  * dmik logging.
551  */
552 #define LogDmik(a)      LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_DMIK,     LOG_GROUP, a)
553
554 /** @def LogSunlover
555  * sunlover logging.
556  */
557 #define LogSunlover(a)  LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_SUNLOVER, LOG_GROUP, a)
558
559 /** @def LogAchim
560  * Achim logging.
561  */
562 #define LogAchim(a)     LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_ACHIM,    LOG_GROUP, a)
563
564 /** @def LogSander
565  * Sander logging.
566  */
567 #define LogSander(a)    LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_SANDER,   LOG_GROUP, a)
568
569 /** @def LogKlaus
570  *  klaus logging.
571  */
572 #define LogKlaus(a)     LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_KLAUS,    LOG_GROUP, a)
573
574 /** @def LogFrank
575  *  frank logging.
576  */
577 #define LogFrank(a)     LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_FRANK,    LOG_GROUP, a)
578
579 /** @def LogBird
580  * bird logging.
581  */
582 #define LogBird(a)      LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_BIRD,     LOG_GROUP, a)
583
584 /** @def LogAleksey
585  * aleksey logging.
586  */
587 #define LogAleksey(a)   LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_ALEKSEY,  LOG_GROUP, a)
588
589 /** @def LogNoName
590  * NoName logging.
591  */
592 #define LogNoName(a)    LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_NONAME,   LOG_GROUP, a)
593
594
595 /** @def LogWarning
596  * The same as Log(), but prepents a <tt>"WARNING! "</tt> string to the message.
597  *
598  * @param   a   Custom log message in format <tt>("string\n" [, args])</tt>.
599  */
600 #if defined(LOG_USE_C99)
601 # define LogWarning(a) \
602     _LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_1, LOG_GROUP, "WARNING! %M", _LogRemoveParentheseis a )
603 #else
604 # define LogWarning(a) \
605     do { Log(("WARNING! ")); Log(a); } while (0)
606 #endif
607
608 /** @def LogTrace
609  * Macro to trace the execution flow: logs the file name, line number and
610  * function name. Can be easily searched for in log files using the
611  * ">>>>>" pattern (prepended to the beginning of each line).
612  */
613 #define LogTrace() \
614     LogFlow((">>>>> %s (%d): " LOG_FN_FMT "\n", __FILE__, __LINE__, __PRETTY_FUNCTION__))
615
616 /** @def LogTraceMsg
617  * The same as LogTrace but logs a custom log message right after the trace line.
618  *
619  * @param   a   Custom log message in format <tt>("string\n" [, args])</tt>.
620  */
621 #ifdef LOG_USE_C99
622 # define LogTraceMsg(a) \
623     _LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_FLOW, LOG_GROUP, ">>>>> %s (%d): " LOG_FN_FMT ": %M", __FILE__, __LINE__, __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
624 #else
625 # define LogTraceMsg(a) \
626     do {  LogFlow((">>>>> %s (%d): " LOG_FN_FMT ": ", __FILE__, __LINE__, __PRETTY_FUNCTION__)); LogFlow(a); } while (0)
627 #endif
628
629 /** @def LogFunc
630  * Level 1 logging inside C/C++ functions.
631  *
632  * Prepends the given log message with the function name followed by a
633  * semicolon and space.
634  *
635  * @param   a   Log message in format <tt>("string\n" [, args])</tt>.
636  */
637 #ifdef LOG_USE_C99
638 # define LogFunc(a) \
639     _LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_1, LOG_GROUP, LOG_FN_FMT ": %M", __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
640 #else
641 # define LogFunc(a) \
642     do { Log((LOG_FN_FMT ": ", __PRETTY_FUNCTION__)); Log(a); } while (0)
643 #endif
644
645 /** @def LogThisFunc
646  * The same as LogFunc but for class functions (methods): the resulting log
647  * line is additionally prepended with a hex value of |this| pointer.
648  *
649  * @param   a   Log message in format <tt>("string\n" [, args])</tt>.
650  */
651 #ifdef LOG_USE_C99
652 # define LogThisFunc(a) \
653     _LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_1, LOG_GROUP, "{%p} " LOG_FN_FMT ": %M", this, __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
654 #else
655 # define LogThisFunc(a) \
656     do { Log(("{%p} " LOG_FN_FMT ": ", this, __PRETTY_FUNCTION__)); Log(a); } while (0)
657 #endif
658
659 /** @def LogFlowFunc
660  * Macro to log the execution flow inside C/C++ functions.
661  *
662  * Prepends the given log message with the function name followed by
663  * a semicolon and space.
664  *
665  * @param   a   Log message in format <tt>("string\n" [, args])</tt>.
666  */
667 #ifdef LOG_USE_C99
668 # define LogFlowFunc(a) \
669     _LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_FLOW, LOG_GROUP, LOG_FN_FMT ": %M", __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
670 #else
671 # define LogFlowFunc(a) \
672     do { LogFlow((LOG_FN_FMT ": ", __PRETTY_FUNCTION__)); LogFlow(a); } while (0)
673 #endif
674
675 /** @def LogWarningFunc
676  * The same as LogWarning(), but prepents the log message with the function name.
677  *
678  * @param   a   Log message in format <tt>("string\n" [, args])</tt>.
679  */
680 #ifdef LOG_USE_C99
681 # define LogWarningFunc(a) \
682     _LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_1, LOG_GROUP, LOG_FN_FMT ": WARNING! %M", __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
683 #else
684 # define LogWarningFunc(a) \
685     do { Log((LOG_FN_FMT ": WARNING! ", __PRETTY_FUNCTION__)); Log(a); } while (0)
686 #endif
687
688 /** @def LogFlowThisFunc
689  * The same as LogFlowFunc but for class functions (methods): the resulting log
690  * line is additionally prepended with a hex value of |this| pointer.
691  *
692  * @param   a   Log message in format <tt>("string\n" [, args])</tt>.
693  */
694 #ifdef LOG_USE_C99
695 # define LogFlowThisFunc(a) \
696     _LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_FLOW, LOG_GROUP, "{%p} " LOG_FN_FMT ": %M", this, __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
697 #else
698 # define LogFlowThisFunc(a) \
699     do { LogFlow(("{%p} " LOG_FN_FMT ": ", this, __PRETTY_FUNCTION__)); LogFlow(a); } while (0)
700 #endif
701
702 /** @def LogWarningThisFunc
703  * The same as LogWarningFunc() but for class functions (methods): the resulting
704  * log line is additionally prepended with a hex value of |this| pointer.
705  *
706  * @param   a   Log message in format <tt>("string\n" [, args])</tt>.
707  */
708 #ifdef LOG_USE_C99
709 # define LogWarningThisFunc(a) \
710     _LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_1, LOG_GROUP, "{%p} " LOG_FN_FMT ": WARNING! %M", this, __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
711 #else
712 # define LogWarningThisFunc(a) \
713     do { Log(("{%p} " LOG_FN_FMT ": WARNING! ", this, __PRETTY_FUNCTION__)); Log(a); } while (0)
714 #endif
715
716 /** Shortcut to |LogFlowFunc ("ENTER\n")|, marks the beginnig of the function. */
717 #define LogFlowFuncEnter()      LogFlowFunc(("ENTER\n"))
718
719 /** Shortcut to |LogFlowFunc ("LEAVE\n")|, marks the end of the function. */
720 #define LogFlowFuncLeave()      LogFlowFunc(("LEAVE\n"))
721
722 /** Shortcut to |LogFlowThisFunc ("ENTER\n")|, marks the beginnig of the function. */
723 #define LogFlowThisFuncEnter()  LogFlowThisFunc(("ENTER\n"))
724
725 /** Shortcut to |LogFlowThisFunc ("LEAVE\n")|, marks the end of the function. */
726 #define LogFlowThisFuncLeave()  LogFlowThisFunc(("LEAVE\n"))
727
728 /** @def LogObjRefCnt
729  * Helper macro to print the current reference count of the given COM object
730  * to the log file.
731  *
732  * @param pObj  Pointer to the object in question (must be a pointer to an
733  *              IUnknown subclass or simply define COM-style AddRef() and
734  *              Release() methods)
735  *
736  * @note Use it only for temporary debugging. It leaves dummy code even if
737  *       logging is disabled.
738  */
739 #define LogObjRefCnt(pObj) \
740     do { \
741         int refc = (pObj)->AddRef(); \
742         LogFlow((#pObj "{%p}.refCnt=%d\n", (pObj), refc - 1)); \
743         (pObj)->Release(); \
744     } while (0)
745
746
747 /** @def LogIsItEnabled
748  * Checks whether the specified logging group is enabled or not.
749  */
750 #ifdef LOG_ENABLED
751 # define LogIsItEnabled(pvInst, fFlags, iGroup) \
752     LogIsItEnabledInternal((pvInst), (unsigned)(iGroup), (unsigned)(fFlags))
753 #else
754 # define LogIsItEnabled(pvInst, fFlags, iGroup) (false)
755 #endif
756
757 /** @def LogIsEnabled
758  * Checks whether level 1 logging is enabled.
759  */
760 #define LogIsEnabled()      LogIsItEnabled(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_1, LOG_GROUP)
761
762 /** @def LogIs2Enabled
763  * Checks whether level 2 logging is enabled.
764  */
765 #define LogIs2Enabled()     LogIsItEnabled(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_2, LOG_GROUP)
766
767 /** @def LogIs3Enabled
768  * Checks whether level 3 logging is enabled.
769  */
770 #define LogIs3Enabled()     LogIsItEnabled(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_3, LOG_GROUP)
771
772 /** @def LogIs4Enabled
773  * Checks whether level 4 logging is enabled.
774  */
775 #define LogIs4Enabled()     LogIsItEnabled(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_4, LOG_GROUP)
776
777 /** @def LogIs5Enabled
778  * Checks whether level 5 logging is enabled.
779  */
780 #define LogIs5Enabled()     LogIsItEnabled(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_5, LOG_GROUP)
781
782 /** @def LogIs6Enabled
783  * Checks whether level 6 logging is enabled.
784  */
785 #define LogIs6Enabled()     LogIsItEnabled(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_6, LOG_GROUP)
786
787 /** @def LogIsFlowEnabled
788  * Checks whether execution flow logging is enabled.
789  */
790 #define LogIsFlowEnabled()  LogIsItEnabled(LOG_INSTANCE, RTLOGGRPFLAGS_FLOW, LOG_GROUP)
791
792
793
794
795 /** @name Release Logging
796  * @{
797  */
798
799 #ifdef DOXYGEN_RUNNING
800 # define RTLOG_REL_DISABLED
801 # define RTLOG_REL_ENABLED
802 #endif
803
804 /** @def RTLOG_REL_DISABLED
805  * Use this compile time define to disable all release logging
806  * macros.
807  */
808
809 /** @def RTLOG_REL_ENABLED
810  * Use this compile time define to override RTLOG_REL_DISABLE.
811  */
812
813 /*
814  * Determin whether release logging is enabled and forcefully normalize the indicators.
815  */
816 #if !defined(RTLOG_REL_DISABLED) || defined(RTLOG_REL_ENABLED)
817 # undef  RTLOG_REL_DISABLED
818 # undef  RTLOG_REL_ENABLED
819 # define RTLOG_REL_ENABLED
820 #else
821 # undef  RTLOG_REL_ENABLED
822 # undef  RTLOG_REL_DISABLED
823 # define RTLOG_REL_DISABLED
824 #endif
825
826
827 /** @def LogIt
828  * Write to specific logger if group enabled.
829  */
830 #ifdef RTLOG_REL_ENABLED
831 # if defined(LOG_USE_C99)
832 define _LogRelRemoveParentheseis(...)                __VA_ARGS__
833 #   define _LogRelIt(pvInst, fFlags, iGroup, ...)       RTLogLoggerEx((PRTLOGGER)pvInst, fFlags, iGroup, __VA_ARGS__)
834 #   define LogRelIt(pvInst, fFlags, iGroup, fmtargs) \
835     do \
836     { \
837         PRTLOGGER LogRelIt_pLogger = (PRTLOGGER)(pvInst) ? (PRTLOGGER)(pvInst) : RTLogRelDefaultInstance(); \
838         if (LogRelIt_pLogger) \
839             _LogRelIt(LogRelIt_pLogger, fFlags, iGroup, _LogRelRemoveParentheseis fmtargs); \
840         LogIt(LOG_INSTANCE, fFlags, iGroup, fmtargs); \
841     } while (0)
842 # else
843 define LogRelIt(pvInst, fFlags, iGroup, fmtargs) \
844    do \
845    { \
846        PRTLOGGER LogRelIt_pLogger = (PRTLOGGER)(pvInst) ? (PRTLOGGER)(pvInst) : RTLogRelDefaultInstance(); \
847        if (LogRelIt_pLogger) \
848        { \
849            unsigned LogIt_fFlags = LogRelIt_pLogger->afGroups[(unsigned)(iGroup) < LogRelIt_pLogger->cGroups ? (unsigned)(iGroup) : 0]; \
850            if ((LogIt_fFlags & ((fFlags) | RTLOGGRPFLAGS_ENABLED)) == ((fFlags) | RTLOGGRPFLAGS_ENABLED)) \
851                LogRelIt_pLogger->pfnLogger fmtargs; \
852        } \
853        LogIt(LOG_INSTANCE, fFlags, iGroup, fmtargs); \
854   } while (0)
855 # endif
856 #else   /* !RTLOG_REL_ENABLED */
857 # define LogRelIt(pvInst, fFlags, iGroup, fmtargs)      do { } while (0)
858 # if defined(LOG_USE_C99)
859 define _LogRelRemoveParentheseis(...)                __VA_ARGS__
860 define _LogRelIt(pvInst, fFlags, iGroup, ...)        do { } while (0)
861 # endif
862 #endif  /* !RTLOG_REL_ENABLED */
863
864
865 /** @def LogRel
866  * Level 1 logging.
867  */
868 #define LogRel(a)          LogRelIt(LOG_REL_INSTANCE, RTLOGGRPFLAGS_LEVEL_1, LOG_GROUP, a)
869
870 /** @def LogRel2
871  * Level 2 logging.
872  */
873 #define LogRel2(a)         LogRelIt(LOG_R