9f9fd5dfcfe6cf3c68f056a9587614b23d73989a
[gpgme.git] / src / debug.h
1 /* debug.h - interface to debugging functions
2    Copyright (C) 2002, 2004, 2005, 2007 g10 Code GmbH
3
4    This file is part of GPGME.
5
6    GPGME is free software; you can redistribute it and/or modify it
7    under the terms of the GNU Lesser General Public License as
8    published by the Free Software Foundation; either version 2.1 of
9    the License, or (at your option) any later version.
10
11    GPGME is distributed in the hope that it will be useful, but
12    WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with this program; if not, write to the Free Software
18    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19    02111-1307, USA.  */
20
21 #ifndef DEBUG_H
22 #define DEBUG_H
23
24 #include <string.h>
25 #ifdef HAVE_STDINT_H
26 #include <stdint.h>
27 #endif
28
29 #include "gpgme.h"  /* Required for gpgme_error stuff.  */
30
31
32 /* Indirect stringification, requires __STDC__ to work.  */
33 #define STRINGIFY(v) #v
34 #define XSTRINGIFY(v) STRINGIFY(v)
35
36 \f
37 /*
38  * The debug levels.
39  *
40  * Note that TRACE_LOGBUFX uses the current debug level + 1.
41  */
42
43 #define DEBUG_INIT      1
44 #define DEBUG_GLOBAL    2
45 #define DEBUG_CTX       3
46 #define DEBUG_ENGINE    4
47 #define DEBUG_DATA      5
48 #define DEBUG_ASSUAN    6
49 #define DEBUG_SYSIO     7
50
51 \f
52 /* Remove path components from filenames (i.e. __FILE__) for cleaner
53    logs. */
54 static inline const char *_gpgme_debug_srcname (const char *file)
55                                                 GPGME_GCC_A_PURE;
56
57 static inline const char *
58 _gpgme_debug_srcname (const char *file)
59 {
60   const char *s = strrchr (file, '/');
61   return s? s+1:file;
62 }
63
64 /* Initialization helper function; see debug.c.  */
65 int _gpgme_debug_set_debug_envvar (const char *value);
66
67 /* Called early to initialize the logging.  */
68 void _gpgme_debug_subsystem_init (void);
69
70 /* Log the formatted string FORMAT at debug level LEVEL or higher.  */
71 int  _gpgme_debug (int level, const char *format, ...);
72 int  _gpgme_debugf (int level, int mode,
73                     const char *func, const char *tagname, const char *tagvalue,
74                     const char *format, ...) GPGRT_ATTR_PRINTF(6,7);
75
76
77 /* Start a new debug line in *LINE, logged at level LEVEL or higher,
78    and starting with the formatted string FORMAT.  */
79 void _gpgme_debug_begin (void **helper, int level, const char *format, ...);
80
81 /* Add the formatted string FORMAT to the debug line *LINE.  */
82 void _gpgme_debug_add (void **helper, const char *format, ...);
83
84 /* Finish construction of *LINE and send it to the debug output
85    stream.  */
86 void _gpgme_debug_end (void **helper);
87
88 void _gpgme_debug_buffer (int lvl, const char *const fmt,
89                           const char *const func, const char *const buffer,
90                           size_t len);
91
92 void _gpgme_debug_frame_begin (void);
93 int  _gpgme_debug_frame_end (void);
94
95 static inline gpgme_error_t
96 _gpgme_trace_gpgme_error (gpgme_error_t err, const char *file, int line)
97 {
98   _gpgme_debug (DEBUG_ENGINE, "%s:%d: returning error: %s\n",
99                 _gpgme_debug_srcname (file), line, gpgme_strerror (err));
100   return err;
101 }
102
103 \f
104 /* Trace support.  */
105
106 /* FIXME: For now.  */
107 #define _gpgme_debug_trace() 1
108
109 #define _TRACE(lvl, name, tag)                                  \
110   int _gpgme_trace_level = lvl;                                 \
111   const char *const _gpgme_trace_func = name;                   \
112   const char *const _gpgme_trace_tagname = STRINGIFY (tag);     \
113   void *_gpgme_trace_tag = (void *) (uintptr_t) tag; \
114   _gpgme_debug_frame_begin ()
115
116 #define TRACE_BEG(lvl, name, tag, ...)                     \
117   _TRACE (lvl, name, tag);                                              \
118   _gpgme_debugf (_gpgme_trace_level, 1,                                 \
119                  _gpgme_trace_func, _gpgme_trace_tagname, _gpgme_trace_tag, \
120                   __VA_ARGS__)
121
122 #define TRACE(lvl, name, tag, ...)                                      \
123   _gpgme_debug_frame_begin (),                                          \
124     _gpgme_debugf (lvl, 0,                                              \
125                    name, STRINGIFY (tag), (void *) (uintptr_t) tag,     \
126                    __VA_ARGS__),                                        \
127     _gpgme_debug_frame_end ()
128
129 #define TRACE_ERR(err)                                                  \
130   err == 0 ? (TRACE_SUC ("")) :                                         \
131     (_gpgme_debug (_gpgme_trace_level, "%s:%d: error: %s <%s>\n",       \
132                    _gpgme_trace_func, __LINE__,  gpgme_strerror (err),  \
133                    gpgme_strsource (err)), _gpgme_debug_frame_end (), (err))
134
135
136 /* The cast to void suppresses GCC warnings.  */
137 #define TRACE_SYSRES(res)                                               \
138   res >= 0 ? ((void) (TRACE_SUC ("result=%i", res)), (res)) :           \
139     (_gpgme_debug (_gpgme_trace_level, "%s: error: %s\n",               \
140                    _gpgme_trace_func, strerror (errno)),                \
141      _gpgme_debug_frame_end (), (res))
142 #define TRACE_SYSERR(res)                                               \
143   res == 0 ? ((void) (TRACE_SUC ("result=%i", res)), (res)) :           \
144     (_gpgme_debug (_gpgme_trace_level, "%s: error: %s\n",               \
145                    _gpgme_trace_func, strerror (res)),                  \
146      _gpgme_debug_frame_end (), (res))
147 #define TRACE_SYSERR_NR(res)                                            \
148   do { res == 0 ? ((void) (TRACE_SUC ("result=%i", res)), (res)) :     \
149     (_gpgme_debug (_gpgme_trace_level, "%s: error: %s\n",               \
150                    _gpgme_trace_func, strerror (res)),                  \
151      _gpgme_debug_frame_end ()); } while (0)
152
153 #define TRACE_SUC(...)                                                  \
154   _gpgme_debugf (_gpgme_trace_level, 3, _gpgme_trace_func, NULL, NULL,  \
155                  __VA_ARGS__), _gpgme_debug_frame_end ()
156
157 #define TRACE_LOG(...)                                                  \
158   _gpgme_debugf (_gpgme_trace_level, 2,                                 \
159                  _gpgme_trace_func, _gpgme_trace_tagname, _gpgme_trace_tag, \
160                  __VA_ARGS__)
161
162 #define TRACE_LOGBUF(buf, len)                                  \
163   _gpgme_debug_buffer (_gpgme_trace_level, "%s: check: %s",     \
164                        _gpgme_trace_func, buf, len)
165
166 #define TRACE_LOGBUFX(buf, len)                                 \
167   _gpgme_debug_buffer (_gpgme_trace_level+1, "%s: check: %s",   \
168                        _gpgme_trace_func, buf, len)
169
170 #define TRACE_SEQ(hlp,fmt)                                              \
171   _gpgme_debug_begin (&(hlp), _gpgme_trace_level,                       \
172                       "%s: check: %s=%p, " fmt, _gpgme_trace_func,      \
173                       _gpgme_trace_tagname, _gpgme_trace_tag)
174 #define TRACE_ADD0(hlp,fmt) \
175   _gpgme_debug_add (&(hlp), fmt)
176 #define TRACE_ADD1(hlp,fmt,a) \
177   _gpgme_debug_add (&(hlp), fmt, (a))
178 #define TRACE_ADD2(hlp,fmt,a,b) \
179   _gpgme_debug_add (&(hlp), fmt, (a), (b))
180 #define TRACE_ADD3(hlp,fmt,a,b,c) \
181   _gpgme_debug_add (&(hlp), fmt, (a), (b), (c))
182 #define TRACE_END(hlp,fmt) \
183   _gpgme_debug_add (&(hlp), fmt); \
184   _gpgme_debug_end (&(hlp))
185 #define TRACE_ENABLED(hlp) (!!(hlp))
186
187 /* And finally a simple macro to trace the location of an error code.
188    This macro is independent of the other trace macros and may be used
189    without any preconditions.  */
190 #define trace_gpg_error(e) \
191   _gpgme_trace_gpgme_error (gpg_error (e), __FILE__, __LINE__)
192
193
194 #endif  /* DEBUG_H */