core: Improve the debug messages even more.
[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 (void **line, int level, int mode,
72                    const char *func, const char *tagname, const char *tagvalue,
73                    const char *format, ...) GPGRT_ATTR_PRINTF(7,8);
74
75
76 /* Add the formatted string FORMAT to the debug line *LINE.  */
77 void _gpgme_debug_add (void **helper, const char *format, ...);
78
79 /* Finish construction of *LINE and send it to the debug output
80    stream.  */
81 void _gpgme_debug_end (void **helper);
82
83 void _gpgme_debug_buffer (int lvl, const char *const fmt,
84                           const char *const func, const char *const buffer,
85                           size_t len);
86
87 void _gpgme_debug_frame_begin (void);
88 int  _gpgme_debug_frame_end (void);
89
90 static inline gpgme_error_t
91 _gpgme_trace_gpgme_error (gpgme_error_t err, const char *file, int line)
92 {
93   _gpgme_debug (NULL, DEBUG_ENGINE, -1, NULL, NULL, NULL,
94                 "%s:%d: returning error: %s\n",
95                 _gpgme_debug_srcname (file), line, gpgme_strerror (err));
96   return err;
97 }
98
99 \f
100 /* Trace support.  */
101
102 /* FIXME: For now.  */
103 #define _gpgme_debug_trace() 1
104
105 #define _TRACE(lvl, name, tag)                                  \
106   int _gpgme_trace_level = lvl;                                 \
107   const char *const _gpgme_trace_func = name;                   \
108   const char *const _gpgme_trace_tagname = STRINGIFY (tag);     \
109   void *_gpgme_trace_tag = (void *) (uintptr_t) tag; \
110   _gpgme_debug_frame_begin ()
111
112 /* Note: We can't protect this with a do-while block.  */
113 #define TRACE_BEG(lvl, name, tag, ...)                                  \
114   _TRACE (lvl, name, tag);                                              \
115   _gpgme_debug (NULL, _gpgme_trace_level, 1,                             \
116                 _gpgme_trace_func, _gpgme_trace_tagname, _gpgme_trace_tag, \
117                 __VA_ARGS__)
118
119 #define TRACE(lvl, name, tag, ...) do {                                 \
120     _gpgme_debug_frame_begin ();                                        \
121     _gpgme_debug (NULL, lvl, 0, name, STRINGIFY (tag), (void *)(uintptr_t)tag, \
122                   __VA_ARGS__);                                         \
123     _gpgme_debug_frame_end ();                                          \
124   } while (0)
125
126
127 /* Trace a gpg-error and return it.  */
128 #define TRACE_ERR(err) \
129     _trace_err ((err), _gpgme_trace_level, _gpgme_trace_func, __LINE__)
130 static inline gpg_error_t
131 _trace_err (gpg_error_t err, int lvl, const char *func, int line)
132 {
133   if (!err)
134     _gpgme_debug (NULL, lvl, 3, func, NULL, NULL, "");
135   else
136     _gpgme_debug (NULL, lvl, -1, NULL, NULL, NULL,
137                   "%s:%d: error: %s <%s>\n",
138                   func, line,  gpgme_strerror (err), gpgme_strsource (err));
139   _gpgme_debug_frame_end ();
140   return err;
141 }
142
143 /* Trace a system call result and return it.  */
144 #define TRACE_SYSRES(res) \
145     _trace_sysres ((res), _gpgme_trace_level, _gpgme_trace_func, __LINE__)
146 static inline int
147 _trace_sysres (int res, int lvl, const char *func, int line)
148 {
149   if (res >= 0)
150     _gpgme_debug (NULL, lvl, 3, func, NULL, NULL, "result=%d", res);
151   else
152     _gpgme_debug (NULL, lvl, -1, NULL, NULL, NULL,
153                   "%s:%d: error: %s (%d)\n",
154                   func, line,  strerror (res), res);
155   _gpgme_debug_frame_end ();
156   return res;
157 }
158
159 /* Trace a system call error and return it.  */
160 #define TRACE_SYSERR(rc) \
161     _trace_syserr ((rc), _gpgme_trace_level, _gpgme_trace_func, __LINE__)
162 static inline int
163 _trace_syserr (int rc, int lvl, const char *func, int line)
164 {
165   if (!rc)
166     _gpgme_debug (NULL, lvl, 3, func, NULL, NULL, "result=0");
167   else
168     _gpgme_debug (NULL, lvl, -1, NULL, NULL, NULL,
169                   "%s:%d: error: %s (%d)\n",
170                   func, line, strerror (rc), rc);
171   _gpgme_debug_frame_end ();
172   return rc;
173 }
174
175 #define TRACE_SUC(...) do {                                             \
176     _gpgme_debug (NULL, _gpgme_trace_level, 3, _gpgme_trace_func, NULL, NULL, \
177                   __VA_ARGS__);                                         \
178     _gpgme_debug_frame_end ();                                          \
179   } while (0)
180
181 #define TRACE_LOG(...) do {                                             \
182     _gpgme_debug (NULL, _gpgme_trace_level, 2,                           \
183                   _gpgme_trace_func, _gpgme_trace_tagname, _gpgme_trace_tag, \
184                   __VA_ARGS__);                                         \
185   } while (0)
186
187 #define TRACE_LOGBUF(buf, len) do {                             \
188     _gpgme_debug_buffer (_gpgme_trace_level, "%s: check: %s",   \
189                          _gpgme_trace_func, buf, len);          \
190   } while (0)
191
192 #define TRACE_LOGBUFX(buf, len) do {                                    \
193     _gpgme_debug_buffer (_gpgme_trace_level+1, "%s: check: %s",         \
194                          _gpgme_trace_func, buf, len); \
195   } while (0)
196
197 #define TRACE_SEQ(hlp,...) do {                                               \
198     _gpgme_debug (&(hlp), _gpgme_trace_level, 2, _gpgme_trace_func,            \
199                          _gpgme_trace_tagname, _gpgme_trace_tag, __VA_ARGS__); \
200   } while (0)
201
202 #define TRACE_ADD0(hlp,fmt) \
203   _gpgme_debug_add (&(hlp), fmt)
204 #define TRACE_ADD1(hlp,fmt,a) \
205   _gpgme_debug_add (&(hlp), fmt, (a))
206 #define TRACE_ADD2(hlp,fmt,a,b) \
207   _gpgme_debug_add (&(hlp), fmt, (a), (b))
208 #define TRACE_ADD3(hlp,fmt,a,b,c) \
209   _gpgme_debug_add (&(hlp), fmt, (a), (b), (c))
210 #define TRACE_END(hlp,fmt) \
211   _gpgme_debug_add (&(hlp), fmt); \
212   _gpgme_debug_end (&(hlp))
213
214 #define TRACE_ENABLED(hlp) (!!(hlp))
215
216 /* And finally a simple macro to trace the location of an error code.
217    This macro is independent of the other trace macros and may be used
218    without any preconditions.  */
219 #define trace_gpg_error(e) \
220   _gpgme_trace_gpgme_error (gpg_error (e), __FILE__, __LINE__)
221
222
223 #endif  /* DEBUG_H */