json: Fix t-decrypt-verify.out for GnuPG >= 2.3.
[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 #include <errno.h>
29
30 #include "gpgme.h"  /* Required for gpgme_error stuff.  */
31
32
33 /* Indirect stringification, requires __STDC__ to work.  */
34 #define STRINGIFY(v) #v
35 #define XSTRINGIFY(v) STRINGIFY(v)
36
37 \f
38 /*
39  * The debug levels.
40  *
41  * Note that TRACE_LOGBUFX uses the current debug level + 1.
42  */
43
44 #define DEBUG_INIT      1
45 #define DEBUG_GLOBAL    2
46 #define DEBUG_CTX       3
47 #define DEBUG_ENGINE    4
48 #define DEBUG_DATA      5
49 #define DEBUG_ASSUAN    6
50 #define DEBUG_SYSIO     7
51
52 \f
53 /* Remove path components from filenames (i.e. __FILE__) for cleaner
54    logs. */
55 static inline const char *_gpgme_debug_srcname (const char *file)
56                                                 GPGME_GCC_A_PURE;
57
58 static inline const char *
59 _gpgme_debug_srcname (const char *file)
60 {
61   const char *s = strrchr (file, '/');
62   return s? s+1:file;
63 }
64
65 /* Initialization helper function; see debug.c.  */
66 int _gpgme_debug_set_debug_envvar (const char *value);
67
68 /* Called early to initialize the logging.  */
69 void _gpgme_debug_subsystem_init (void);
70
71 /* Log the formatted string FORMAT at debug level LEVEL or higher.  */
72 int  _gpgme_debug (void **line, int level, int mode,
73                    const char *func, const char *tagname, const char *tagvalue,
74                    const char *format, ...) GPGRT_ATTR_PRINTF(7,8);
75
76
77 /* Add the formatted string FORMAT to the debug line *LINE.  */
78 void _gpgme_debug_add (void **helper, const char *format, ...);
79
80 /* Finish construction of *LINE and send it to the debug output
81    stream.  */
82 void _gpgme_debug_end (void **helper);
83
84 void _gpgme_debug_buffer (int lvl, const char *const fmt,
85                           const char *const func, const char *const buffer,
86                           size_t len);
87
88 void _gpgme_debug_frame_begin (void);
89 int  _gpgme_debug_frame_end (void);
90
91 static inline gpgme_error_t
92 _gpgme_trace_gpgme_error (gpgme_error_t err, const char *file, int line)
93 {
94   _gpgme_debug (NULL, DEBUG_ENGINE, -1, NULL, NULL, NULL,
95                 "%s:%d: returning error: %s\n",
96                 _gpgme_debug_srcname (file), line, gpgme_strerror (err));
97   return err;
98 }
99
100 \f
101 /* Trace support.  */
102
103 /* FIXME: For now.  */
104 #define _gpgme_debug_trace() 1
105
106 #define _TRACE(lvl, name, tag)                                  \
107   int _gpgme_trace_level = lvl;                                 \
108   const char *const _gpgme_trace_func = name;                   \
109   const char *const _gpgme_trace_tagname = STRINGIFY (tag);     \
110   void *_gpgme_trace_tag = (void *) (uintptr_t) tag; \
111   _gpgme_debug_frame_begin ()
112
113 /* Note: We can't protect this with a do-while block.  */
114 #define TRACE_BEG(lvl, name, tag, ...)                                  \
115   _TRACE (lvl, name, tag);                                              \
116   _gpgme_debug (NULL, _gpgme_trace_level, 1,                             \
117                 _gpgme_trace_func, _gpgme_trace_tagname, _gpgme_trace_tag, \
118                 __VA_ARGS__)
119
120 #define TRACE(lvl, name, tag, ...) do {                                 \
121     _gpgme_debug_frame_begin ();                                        \
122     _gpgme_debug (NULL, lvl, 0, name, STRINGIFY (tag), (void *)(uintptr_t)tag, \
123                   __VA_ARGS__);                                         \
124     _gpgme_debug_frame_end ();                                          \
125   } while (0)
126
127
128 /* Trace a gpg-error and return it.  */
129 #define TRACE_ERR(err) \
130     _trace_err ((err), _gpgme_trace_level, _gpgme_trace_func, __LINE__)
131 static inline gpg_error_t
132 _trace_err (gpg_error_t err, int lvl, const char *func, int line)
133 {
134   if (!err)
135     _gpgme_debug (NULL, lvl, 3, func, NULL, NULL, "");
136   else
137     _gpgme_debug (NULL, lvl, -1, NULL, NULL, NULL,
138                   "%s:%d: error: %s <%s>\n",
139                   func, line,  gpgme_strerror (err), gpgme_strsource (err));
140   _gpgme_debug_frame_end ();
141   return err;
142 }
143
144 /* Trace a system call result and return it.  */
145 #define TRACE_SYSRES(res) \
146     _trace_sysres ((res), _gpgme_trace_level, _gpgme_trace_func, __LINE__)
147 static inline int
148 _trace_sysres (int res, int lvl, const char *func, int line)
149 {
150   if (res >= 0)
151     _gpgme_debug (NULL, lvl, 3, func, NULL, NULL, "result=%d", res);
152   else
153     _gpgme_debug (NULL, lvl, -1, NULL, NULL, NULL,
154                   "%s:%d: error: %s (%d)\n",
155                   func, line,  strerror (errno), errno);
156   _gpgme_debug_frame_end ();
157   return res;
158 }
159
160 /* Trace a system call error and return it.  */
161 #define TRACE_SYSERR(rc) \
162     _trace_syserr ((rc), _gpgme_trace_level, _gpgme_trace_func, __LINE__)
163 static inline int
164 _trace_syserr (int rc, int lvl, const char *func, int line)
165 {
166   if (!rc)
167     _gpgme_debug (NULL, lvl, 3, func, NULL, NULL, "result=0");
168   else
169     _gpgme_debug (NULL, lvl, -1, NULL, NULL, NULL,
170                   "%s:%d: error: %s (%d)\n",
171                   func, line, strerror (rc), rc);
172   _gpgme_debug_frame_end ();
173   return rc;
174 }
175
176 #define TRACE_SUC(...) do {                                             \
177     _gpgme_debug (NULL, _gpgme_trace_level, 3, _gpgme_trace_func, NULL, NULL, \
178                   __VA_ARGS__);                                         \
179     _gpgme_debug_frame_end ();                                          \
180   } while (0)
181
182 #define TRACE_LOG(...) do {                                             \
183     _gpgme_debug (NULL, _gpgme_trace_level, 2,                           \
184                   _gpgme_trace_func, _gpgme_trace_tagname, _gpgme_trace_tag, \
185                   __VA_ARGS__);                                         \
186   } while (0)
187
188 #define TRACE_LOGBUF(buf, len) do {                             \
189     _gpgme_debug_buffer (_gpgme_trace_level, "%s: check: %s",   \
190                          _gpgme_trace_func, buf, len);          \
191   } while (0)
192
193 #define TRACE_LOGBUFX(buf, len) do {                                    \
194     _gpgme_debug_buffer (_gpgme_trace_level+1, "%s: check: %s",         \
195                          _gpgme_trace_func, buf, len); \
196   } while (0)
197
198 #define TRACE_SEQ(hlp,...) do {                                               \
199     _gpgme_debug (&(hlp), _gpgme_trace_level, 2, _gpgme_trace_func,            \
200                          _gpgme_trace_tagname, _gpgme_trace_tag, __VA_ARGS__); \
201   } while (0)
202
203 #define TRACE_ADD0(hlp,fmt) \
204   _gpgme_debug_add (&(hlp), fmt)
205 #define TRACE_ADD1(hlp,fmt,a) \
206   _gpgme_debug_add (&(hlp), fmt, (a))
207 #define TRACE_ADD2(hlp,fmt,a,b) \
208   _gpgme_debug_add (&(hlp), fmt, (a), (b))
209 #define TRACE_ADD3(hlp,fmt,a,b,c) \
210   _gpgme_debug_add (&(hlp), fmt, (a), (b), (c))
211 #define TRACE_END(hlp,fmt) \
212   _gpgme_debug_add (&(hlp), fmt); \
213   _gpgme_debug_end (&(hlp))
214
215 #define TRACE_ENABLED(hlp) (!!(hlp))
216
217 /* And finally a simple macro to trace the location of an error code.
218    This macro is independent of the other trace macros and may be used
219    without any preconditions.  */
220 #define trace_gpg_error(e) \
221   _gpgme_trace_gpgme_error (gpg_error (e), __FILE__, __LINE__)
222
223
224 #endif  /* DEBUG_H */