1 /*
2    (c) Copyright 2001-2009  The world wide DirectFB Open Source Community (directfb.org)
3    (c) Copyright 2000-2004  Convergence (integrated media) GmbH
4 
5    All rights reserved.
6 
7    Written by Denis Oliver Kropp <dok@directfb.org>,
8               Andreas Hundt <andi@fischlustig.de>,
9               Sven Neumann <neo@directfb.org>,
10               Ville Syrjälä <syrjala@sci.fi> and
11               Claudio Ciccani <klan@users.sf.net>.
12 
13    This library is free software; you can redistribute it and/or
14    modify it under the terms of the GNU Lesser General Public
15    License as published by the Free Software Foundation; either
16    version 2 of the License, or (at your option) any later version.
17 
18    This library is distributed in the hope that it will be useful,
19    but WITHOUT ANY WARRANTY; without even the implied warranty of
20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21    Lesser General Public License for more details.
22 
23    You should have received a copy of the GNU Lesser General Public
24    License along with this library; if not, write to the
25    Free Software Foundation, Inc., 59 Temple Place - Suite 330,
26    Boston, MA 02111-1307, USA.
27 */
28 
29 #ifndef __DIRECT__DEBUG_H__
30 #define __DIRECT__DEBUG_H__
31 
32 #include <direct/build.h>
33 
34 #include <stdio.h>
35 #include <errno.h>
36 
37 #include <direct/clock.h>
38 #include <direct/conf.h>
39 #include <direct/log.h>
40 #include <direct/messages.h>
41 #include <direct/system.h>
42 #include <direct/thread.h>
43 #include <direct/trace.h>
44 #include <direct/types.h>
45 
46 
47 typedef struct {
48      unsigned int   age;
49      bool           enabled;
50      bool           registered;
51 
52      const char    *name;
53      const char    *description;
54 
55      int            name_len;
56 } DirectDebugDomain;
57 
58 void direct_debug_config_domain( const char *name, bool enable );
59 
60 bool direct_debug_check_domain( DirectDebugDomain *domain );
61 
62 
63 #if DIRECT_BUILD_TEXT
64 
65 #define D_DEBUG_DOMAIN(identifier,name,description)                                  \
66      static DirectDebugDomain identifier __attribute__((unused))                     \
67             = { 0, false, false, name, description, sizeof(name) - 1 }
68 
69 void direct_debug_at_always( DirectDebugDomain *domain,
70                              const char        *format, ... )  D_FORMAT_PRINTF(2);
71 
72 #define d_debug_at( domain, ... )      direct_debug_at_always( &domain, __VA_ARGS__ )
73 
74 
75 #if DIRECT_BUILD_DEBUGS
76 
77 void direct_debug( const char *format, ... )  D_FORMAT_PRINTF(1);
78 
79 void direct_debug_at( DirectDebugDomain *domain,
80                       const char        *format, ... )  D_FORMAT_PRINTF(2);
81 
82 void direct_debug_enter( DirectDebugDomain *domain,
83                          const char *func,
84                          const char *file,
85                          int         line,
86                          const char *format, ... )  D_FORMAT_PRINTF(5);
87 
88 void direct_debug_exit( DirectDebugDomain *domain,
89                         const char *func,
90                         const char *file,
91                         int         line,
92                         const char *format, ... )  D_FORMAT_PRINTF(5);
93 
94 void direct_break( const char *func,
95                    const char *file,
96                    int         line,
97                    const char *format, ... )  D_FORMAT_PRINTF(4);
98 
99 void direct_assertion( const char *exp,
100                        const char *func,
101                        const char *file,
102                        int         line );
103 
104 void direct_assumption( const char *exp,
105                         const char *func,
106                         const char *file,
107                         int         line );
108 #endif
109 
110 #if DIRECT_BUILD_DEBUG || defined(DIRECT_ENABLE_DEBUG) || defined(DIRECT_FORCE_DEBUG)
111 
112 #define D_DEBUG_ENABLED  (1)
113 
114 #define D_DEBUG(...)                                                                \
115      do {                                                                            \
116           if (!direct_config || direct_config->debug)                                \
117                direct_debug( __VA_ARGS__ );                                          \
118      } while (0)
119 
120 
121 #define D_DEBUG_AT(d,...)                                                            \
122      do {                                                                            \
123           direct_debug_at( &d, __VA_ARGS__ );                                        \
124      } while (0)
125 
126 #define D_DEBUG_ENTER(d,...)                                                         \
127      do {                                                                            \
128           direct_debug_enter( &d, __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__ );   \
129      } while (0)
130 
131 #define D_DEBUG_EXIT(d,...)                                                          \
132      do {                                                                            \
133           direct_debug_exit( &d, __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__ );    \
134      } while (0)
135 
136 #define D_ASSERT(exp)                                                                \
137      do {                                                                            \
138           if (!(exp))                                                                \
139                direct_assertion( #exp, __FUNCTION__, __FILE__, __LINE__ );           \
140      } while (0)
141 
142 
143 #define D_ASSUME(exp)                                                                \
144      do {                                                                            \
145           if (!(exp))                                                                \
146                direct_assumption( #exp, __FUNCTION__, __FILE__, __LINE__ );          \
147      } while (0)
148 
149 
150 #define D_BREAK(...)                                                                 \
151      do {                                                                            \
152           direct_break( __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__ );             \
153      } while (0)
154 
155 #define D_DEBUG_CHECK(d)                                                             \
156      direct_debug_check_domain( &d )
157 
158 #elif defined(DIRECT_MINI_DEBUG)
159 
160 /*
161  * Mini debug mode, only D_DEBUG_AT, no domain filters, simple assertion
162  */
163 
164 #define D_DEBUG_ENABLED  (2)
165 
166 #define D_DEBUG_AT(d,...)                                                            \
167      do {                                                                            \
168           if (direct_config->debug) direct_debug_at_always( &d, __VA_ARGS__ );       \
169      } while (0)
170 
171 #define D_CHECK(exp, aa)                                                             \
172      do {                                                                            \
173           if (!(exp)) {                                                              \
174                long long   millis = direct_clock_get_millis();                       \
175                const char *name   = direct_thread_self_name();                       \
176                                                                                      \
177                direct_log_printf( NULL,                                              \
178                                   "(!) [%-15s %3lld.%03lld] (%5d) *** " #aa " [%s] failed *** [%s:%d in %s()]\n",  \
179                                   name ? name : "  NO NAME  ", millis / 1000LL, millis % 1000LL,                   \
180                                   direct_gettid(), #exp, __FILE__, __LINE__, __FUNCTION__ );                       \
181                                                                                      \
182                direct_trace_print_stack( NULL );                                     \
183           }                                                                          \
184      } while (0)
185 
186 #define D_ASSERT(exp)    D_CHECK(exp, Assertion)
187 #define D_ASSUME(exp)    D_CHECK(exp, Assumption)
188 
189 #define D_DEBUG_CHECK(d)                                                             \
190      direct_config->debug
191 
192 #endif    /* MINI_DEBUG  / DIRECT_BUILD_DEBUG || DIRECT_ENABLE_DEBUG || DIRECT_FORCE_DEBUG */
193 
194 #endif    /* DIRECT_BUILD_TEXT */
195 
196 
197 /*
198  * Fallback definitions, e.g. without DIRECT_BUILD_TEXT or DIRECT_ENABLE_DEBUG
199  */
200 
201 #ifndef D_DEBUG_ENABLED
202 #define D_DEBUG_ENABLED  (0)
203 #endif
204 
205 #ifndef D_DEBUG
206 #define D_DEBUG(...)               do {} while (0)
207 #endif
208 
209 #ifndef D_DEBUG_AT
210 #define D_DEBUG_AT(d,...)          do {} while (0)
211 #endif
212 
213 #ifndef D_DEBUG_ENTER
214 #define D_DEBUG_ENTER(d,...)       do {} while (0)
215 #endif
216 
217 #ifndef D_DEBUG_EXIT
218 #define D_DEBUG_EXIT(d,...)        do {} while (0)
219 #endif
220 
221 #ifndef D_ASSERT
222 #define D_ASSERT(exp)              do {} while (0)
223 #endif
224 
225 #ifndef D_ASSUME
226 #define D_ASSUME(exp)              do {} while (0)
227 #endif
228 
229 #ifndef D_DEBUG_CHECK
230 #define D_DEBUG_CHECK(d)           false
231 #endif
232 
233 #ifndef D_BREAK
234 #define D_BREAK(...)               do {} while (0)
235 #endif
236 
237 #ifndef d_debug_at
238 #define d_debug_at( domain, ... )  do {} while (0)
239 #endif
240 
241 #ifndef D_DEBUG_DOMAIN
242 #define D_DEBUG_DOMAIN(i,n,d)
243 #endif
244 
245 
246 
247 /*
248  * Magic Assertions & Utilities
249  */
250 
251 #define D_MAGIC(spell)             ( (((spell)[sizeof(spell)*8/9] << 24) | \
252                                       ((spell)[sizeof(spell)*7/9] << 16) | \
253                                       ((spell)[sizeof(spell)*6/9] <<  8) | \
254                                       ((spell)[sizeof(spell)*5/9]      )) ^  \
255                                      (((spell)[sizeof(spell)*4/9] << 24) | \
256                                       ((spell)[sizeof(spell)*3/9] << 16) | \
257                                       ((spell)[sizeof(spell)*2/9] <<  8) | \
258                                       ((spell)[sizeof(spell)*1/9]      )) )
259 
260 
261 #define D_MAGIC_SET(o,m)           do {                                              \
262                                         D_ASSERT( (o) != NULL );                     \
263                                         D_ASSUME( (o)->magic != D_MAGIC(#m) );       \
264                                                                                      \
265                                         (o)->magic = D_MAGIC(#m);                    \
266                                    } while (0)
267 
268 #define D_MAGIC_SET_ONLY(o,m)      do {                                              \
269                                         D_ASSERT( (o) != NULL );                     \
270                                                                                      \
271                                         (o)->magic = D_MAGIC(#m);                    \
272                                    } while (0)
273 
274 #define D_MAGIC_ASSERT(o,m)        do {                                              \
275                                         D_ASSERT( (o) != NULL );                     \
276                                         D_ASSERT( (o)->magic == D_MAGIC(#m) );       \
277                                    } while (0)
278 
279 #define D_MAGIC_ASSUME(o,m)        do {                                              \
280                                         D_ASSUME( (o) != NULL );                     \
281                                         if (o)                                       \
282                                              D_ASSUME( (o)->magic == D_MAGIC(#m) );  \
283                                    } while (0)
284 
285 #define D_MAGIC_ASSERT_IF(o,m)     do {                                              \
286                                         if (o)                                       \
287                                              D_ASSERT( (o)->magic == D_MAGIC(#m) );  \
288                                    } while (0)
289 
290 #define D_MAGIC_CLEAR(o)           do {                                              \
291                                         D_ASSERT( (o) != NULL );                     \
292                                         D_ASSUME( (o)->magic != 0 );                 \
293                                                                                      \
294                                         (o)->magic = 0;                              \
295                                    } while (0)
296 
297 
298 #endif
299 
300