1 |
1254 |
phoenix |
#ifndef CYGONCE_INFRA_CYG_ASS_H
|
2 |
|
|
#define CYGONCE_INFRA_CYG_ASS_H
|
3 |
|
|
|
4 |
|
|
//==========================================================================
|
5 |
|
|
//
|
6 |
|
|
// cyg_ass.h
|
7 |
|
|
//
|
8 |
|
|
// Macros and prototypes for the assert system
|
9 |
|
|
//
|
10 |
|
|
//==========================================================================
|
11 |
|
|
//####COPYRIGHTBEGIN####
|
12 |
|
|
//
|
13 |
|
|
// ----------------------------------------------------------------------------
|
14 |
|
|
// Copyright (C) 1997, 1998, 1999, 2000 Red Hat, Inc.
|
15 |
|
|
//
|
16 |
|
|
// This file is part of the eCos host tools.
|
17 |
|
|
//
|
18 |
|
|
// This program is free software; you can redistribute it and/or modify it
|
19 |
|
|
// under the terms of the GNU General Public License as published by the Free
|
20 |
|
|
// Software Foundation; either version 2 of the License, or (at your option)
|
21 |
|
|
// any later version.
|
22 |
|
|
//
|
23 |
|
|
// This program is distributed in the hope that it will be useful, but WITHOUT
|
24 |
|
|
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
25 |
|
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
26 |
|
|
// more details.
|
27 |
|
|
//
|
28 |
|
|
// You should have received a copy of the GNU General Public License along with
|
29 |
|
|
// this program; if not, write to the Free Software Foundation, Inc.,
|
30 |
|
|
// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
31 |
|
|
//
|
32 |
|
|
// ----------------------------------------------------------------------------
|
33 |
|
|
//
|
34 |
|
|
//####COPYRIGHTEND####
|
35 |
|
|
//==========================================================================
|
36 |
|
|
//#####DESCRIPTIONBEGIN####
|
37 |
|
|
//
|
38 |
|
|
// Author(s): nickg from an original by hmt
|
39 |
|
|
// Contributors: nickg
|
40 |
|
|
// Date: 1997-09-08
|
41 |
|
|
// Purpose: Use asserts to avoid writing duff code.
|
42 |
|
|
// Description: Runtime tests that compile to nothing in
|
43 |
|
|
// release versions of the code, to allow
|
44 |
|
|
// as-you-go testing of alternate builds.
|
45 |
|
|
// Usage: #include <cyg/infra/cyg_ass.h>
|
46 |
|
|
// ...
|
47 |
|
|
// CYG_ASSERT( pcount > 0, "Number of probes should be > 0!" );
|
48 |
|
|
//
|
49 |
|
|
// which can result, for example, in a message of the form:
|
50 |
|
|
// ASSERT FAILED: probemgr.cxx:1340, scan_probes() :
|
51 |
|
|
// number of probes should be > 0!
|
52 |
|
|
// if the boolean "pcount > 0" is false.
|
53 |
|
|
//
|
54 |
|
|
//####DESCRIPTIONEND####
|
55 |
|
|
//
|
56 |
|
|
//==========================================================================
|
57 |
|
|
|
58 |
|
|
#include <pkgconf/infra.h>
|
59 |
|
|
|
60 |
|
|
#include <cyg/infra/cyg_type.h> // for CYGBLD_ATTRIB_NORET
|
61 |
|
|
|
62 |
|
|
// -------------------------------------------------------------------------
|
63 |
|
|
// If we do not have a function name macro, define it ourselves
|
64 |
|
|
|
65 |
|
|
#ifndef CYGDBG_INFRA_DEBUG_FUNCTION_PSEUDOMACRO
|
66 |
|
|
// __PRETTY_FUNCTION__ does not work
|
67 |
|
|
# ifndef __PRETTY_FUNCTION__ // And it is not already defined
|
68 |
|
|
# define __PRETTY_FUNCTION__ NULL
|
69 |
|
|
# endif
|
70 |
|
|
#endif
|
71 |
|
|
|
72 |
|
|
// -------------------------------------------------------------------------
|
73 |
|
|
// this is executed to deal with failure - breakpoint it first!
|
74 |
|
|
|
75 |
|
|
externC void
|
76 |
|
|
cyg_assert_fail( const char* /* psz_func */, const char* /* psz_file */,
|
77 |
|
|
cyg_uint32 /* linenum */, const char* /* psz_msg */ )
|
78 |
|
|
CYGBLD_ATTRIB_NORET;
|
79 |
|
|
|
80 |
|
|
// -------------------------------------------------------------------------
|
81 |
|
|
|
82 |
|
|
#ifdef CYGDBG_USE_ASSERTS
|
83 |
|
|
|
84 |
|
|
// -------------------------------------------------------------------------
|
85 |
|
|
// We define macros and appropriate prototypes for the assert/fail
|
86 |
|
|
// system. These are:
|
87 |
|
|
// CYG_FAIL - unconditional panic
|
88 |
|
|
// CYG_ASSERT - panic if boolean expression is false
|
89 |
|
|
// CYG_ASSERTC - compact version of CYG_ASSERT
|
90 |
|
|
|
91 |
|
|
# ifdef CYGDBG_INFRA_DEBUG_ASSERT_MESSAGE
|
92 |
|
|
# define CYG_ASSERT_DOCALL( _msg_ ) \
|
93 |
|
|
cyg_assert_fail( __PRETTY_FUNCTION__, __FILE__, __LINE__, _msg_ );
|
94 |
|
|
# else
|
95 |
|
|
# define CYG_ASSERT_DOCALL( _msg_ ) \
|
96 |
|
|
CYG_MACRO_START \
|
97 |
|
|
const char* _tmp1_ = _msg_; \
|
98 |
|
|
_tmp1_ = _tmp1_; \
|
99 |
|
|
cyg_assert_fail( __PRETTY_FUNCTION__, __FILE__, __LINE__, NULL ); \
|
100 |
|
|
CYG_MACRO_END
|
101 |
|
|
# endif
|
102 |
|
|
|
103 |
|
|
// unconditional failure; use like panic(), coredump() &c.
|
104 |
|
|
# define CYG_FAIL( _msg_ ) \
|
105 |
|
|
CYG_MACRO_START \
|
106 |
|
|
CYG_ASSERT_DOCALL( _msg_ ); \
|
107 |
|
|
CYG_MACRO_END
|
108 |
|
|
|
109 |
|
|
// conditioned assert; if the condition is false, fail.
|
110 |
|
|
# define CYG_ASSERT( _bool_, _msg_ ) \
|
111 |
|
|
CYG_MACRO_START \
|
112 |
|
|
if ( ! ( _bool_ ) ) \
|
113 |
|
|
CYG_ASSERT_DOCALL( _msg_ ); \
|
114 |
|
|
CYG_MACRO_END
|
115 |
|
|
|
116 |
|
|
# define CYG_ASSERTC( _bool_ ) \
|
117 |
|
|
CYG_MACRO_START \
|
118 |
|
|
if ( ! ( _bool_ ) ) \
|
119 |
|
|
CYG_ASSERT_DOCALL( #_bool_ );\
|
120 |
|
|
CYG_MACRO_END
|
121 |
|
|
|
122 |
|
|
#else // ! CYGDBG_USE_ASSERTS
|
123 |
|
|
|
124 |
|
|
// -------------------------------------------------------------------------
|
125 |
|
|
// No asserts: we define empty statements for assert & fail.
|
126 |
|
|
|
127 |
|
|
# define CYG_FAIL( _msg_ ) CYG_EMPTY_STATEMENT
|
128 |
|
|
# define CYG_ASSERT( _bool_, _msg_ ) CYG_EMPTY_STATEMENT
|
129 |
|
|
# define CYG_ASSERTC( _bool_ ) CYG_EMPTY_STATEMENT
|
130 |
|
|
|
131 |
|
|
#endif // ! CYGDBG_USE_ASSERTS
|
132 |
|
|
|
133 |
|
|
// -------------------------------------------------------------------------
|
134 |
|
|
// Pointer integrity checks.
|
135 |
|
|
// These check not only for NULL pointer, but can also check for pointers
|
136 |
|
|
// that are outside to defined memory areas of the platform or executable.
|
137 |
|
|
// We differentiate between data and function pointers, so that we can cope
|
138 |
|
|
// with different formats, and so we can check them against different memory
|
139 |
|
|
// regions.
|
140 |
|
|
|
141 |
|
|
externC cyg_bool cyg_check_data_ptr(void *ptr);
|
142 |
|
|
externC cyg_bool cyg_check_func_ptr(void (*ptr)(void));
|
143 |
|
|
|
144 |
|
|
#ifdef CYGDBG_USE_ASSERTS
|
145 |
|
|
|
146 |
|
|
# define CYG_CHECK_DATA_PTR( _ptr_, _msg_ ) \
|
147 |
|
|
CYG_MACRO_START \
|
148 |
|
|
if( !cyg_check_data_ptr((void *)(_ptr_))) \
|
149 |
|
|
CYG_ASSERT_DOCALL( _msg_ ); \
|
150 |
|
|
CYG_MACRO_END
|
151 |
|
|
|
152 |
|
|
# define CYG_CHECK_FUNC_PTR( _ptr_, _msg_ ) \
|
153 |
|
|
CYG_MACRO_START \
|
154 |
|
|
if( !cyg_check_func_ptr((void (*)(void))(_ptr_))) \
|
155 |
|
|
CYG_ASSERT_DOCALL( _msg_ ); \
|
156 |
|
|
CYG_MACRO_END
|
157 |
|
|
|
158 |
|
|
# define CYG_CHECK_DATA_PTRC( _ptr_ ) \
|
159 |
|
|
CYG_MACRO_START \
|
160 |
|
|
if ( !cyg_check_data_ptr((void *)(_ptr_))) \
|
161 |
|
|
CYG_ASSERT_DOCALL("data pointer (" #_ptr_ ") is valid");\
|
162 |
|
|
CYG_MACRO_END
|
163 |
|
|
|
164 |
|
|
# define CYG_CHECK_FUNC_PTRC( _ptr_ ) \
|
165 |
|
|
CYG_MACRO_START \
|
166 |
|
|
if ( !cyg_check_func_ptr((void (*)(void))(_ptr_))) \
|
167 |
|
|
CYG_ASSERT_DOCALL("function pointer (" #_ptr_ ") is valid"); \
|
168 |
|
|
CYG_MACRO_END
|
169 |
|
|
|
170 |
|
|
#else // CYGDBG_USE_ASSERTS
|
171 |
|
|
|
172 |
|
|
# define CYG_CHECK_DATA_PTR( _ptr_, _msg_ ) CYG_EMPTY_STATEMENT
|
173 |
|
|
# define CYG_CHECK_FUNC_PTR( _ptr_, _msg_ ) CYG_EMPTY_STATEMENT
|
174 |
|
|
# define CYG_CHECK_DATA_PTRC( _ptr_ ) CYG_EMPTY_STATEMENT
|
175 |
|
|
# define CYG_CHECK_FUNC_PTRC( _ptr_ ) CYG_EMPTY_STATEMENT
|
176 |
|
|
|
177 |
|
|
#endif // CYGDBG_USE_ASSERTS
|
178 |
|
|
|
179 |
|
|
// -------------------------------------------------------------------------
|
180 |
|
|
// Unconditional definitions:
|
181 |
|
|
|
182 |
|
|
// Check an object for validity by calling its own checker.
|
183 |
|
|
// Usage:
|
184 |
|
|
// ClassThing *p = &classobject;
|
185 |
|
|
// CYG_ASSERTCLASS( p, "Object at p is broken!" );
|
186 |
|
|
|
187 |
|
|
// this enum gives some options as to how keenly to test; avoids cluttering
|
188 |
|
|
// the member function declaration if the implementor wants to do more
|
189 |
|
|
// zealous tests themselves.
|
190 |
|
|
|
191 |
|
|
enum cyg_assert_class_zeal {
|
192 |
|
|
cyg_system_test = -1,
|
193 |
|
|
cyg_none = 0,
|
194 |
|
|
cyg_trivial,
|
195 |
|
|
cyg_quick,
|
196 |
|
|
cyg_thorough,
|
197 |
|
|
cyg_extreme
|
198 |
|
|
};
|
199 |
|
|
|
200 |
|
|
// -------------------------------------------------------------------------
|
201 |
|
|
// Define macros for checking classes:
|
202 |
|
|
//
|
203 |
|
|
// CYG_ASSERT_CLASS - do proforma check on a class pointer
|
204 |
|
|
// CYG_ASSERT_CLASSO - do proforma check on a class object
|
205 |
|
|
// CYG_ASSERT_ZERO_OR_CLASS- a class pointer is NULL or valid
|
206 |
|
|
// CYG_ASSERT_THIS - "this" is valid
|
207 |
|
|
// + 3 compact variants and two aliases for backwards compatibility.
|
208 |
|
|
//
|
209 |
|
|
// All of these end up going via CYG_ASSERT(), which will be an empty
|
210 |
|
|
// statement if CYGDBG_USE_ASSERTS is disabled. There is no need to
|
211 |
|
|
// test CYGDBG_USE_ASSERTS again here.
|
212 |
|
|
//
|
213 |
|
|
// The idiom required is that a class have a member function called
|
214 |
|
|
// "bool check_this( cyg_assert_class_zeal ) const" that returns true
|
215 |
|
|
// iff the object is OK. This need not be conditionally compiled against
|
216 |
|
|
// CYGDBG_USE_ASSERTS but it can be if only this macro is used to
|
217 |
|
|
// invoke it. Alternatively it can be invoked by hand with other
|
218 |
|
|
// choices from the above enum.
|
219 |
|
|
|
220 |
|
|
// Assert the checker function of an object by pointer, or in hand.
|
221 |
|
|
|
222 |
|
|
#ifdef __cplusplus
|
223 |
|
|
|
224 |
|
|
# ifndef CYG_ASSERT_CLASS_ZEAL
|
225 |
|
|
# define CYG_ASSERT_CLASS_ZEAL (cyg_quick) // can be redefined locally
|
226 |
|
|
# endif
|
227 |
|
|
|
228 |
|
|
# define CYG_ASSERT_CLASS( _pobj_, _msg_ ) \
|
229 |
|
|
CYG_ASSERT( ((0 != (_pobj_)) && \
|
230 |
|
|
(_pobj_)->check_this( CYG_ASSERT_CLASS_ZEAL )), _msg_ )
|
231 |
|
|
|
232 |
|
|
# define CYG_ASSERTCLASS( _pobj_,_msg_) \
|
233 |
|
|
CYG_ASSERT_CLASS( (_pobj_), _msg_ )
|
234 |
|
|
|
235 |
|
|
# define CYG_ASSERT_CLASSO( _obj_, _msg_ ) \
|
236 |
|
|
CYG_ASSERT( (_obj_).check_this( CYG_ASSERT_CLASS_ZEAL ), _msg_ )
|
237 |
|
|
|
238 |
|
|
# define CYG_ASSERTCLASSO( _obj_, _msg_ ) \
|
239 |
|
|
CYG_ASSERT_CLASSO( (_obj_), _msg_ )
|
240 |
|
|
|
241 |
|
|
# define CYG_ASSERT_ZERO_OR_CLASS( _pobj_, _msg_ ) \
|
242 |
|
|
CYG_ASSERT( ((0 == (_pobj_)) || \
|
243 |
|
|
(_pobj_)->check_this( CYG_ASSERT_CLASS_ZEAL )), _msg_ )
|
244 |
|
|
|
245 |
|
|
# define CYG_ASSERT_THIS( _msg_ ) \
|
246 |
|
|
CYG_ASSERT( this->check_this( CYG_ASSERT_CLASS_ZEAL ), _msg_ )
|
247 |
|
|
|
248 |
|
|
# define CYG_ASSERT_CLASSC( _pobj_ ) \
|
249 |
|
|
CYG_ASSERT_CLASS( (_pobj_), "class pointer (" #_pobj_ ") is valid" )
|
250 |
|
|
|
251 |
|
|
# define CYG_ASSERT_CLASSOC( _obj_ ) \
|
252 |
|
|
CYG_ASSERT_CLASSO( (_obj_), "object (" #_obj_ ") is valid" )
|
253 |
|
|
|
254 |
|
|
# define CYG_ASSERT_ZERO_OR_CLASSC( _pobj_ ) \
|
255 |
|
|
CYG_ASSERT_ZERO_OR_CLASS((_pobj_), \
|
256 |
|
|
"class pointer (" #_pobj_ ") is zero or valid")
|
257 |
|
|
|
258 |
|
|
# define CYG_ASSERT_THISC( ) \
|
259 |
|
|
CYG_ASSERT_THIS( "\"this\" pointer is valid" )
|
260 |
|
|
|
261 |
|
|
#define CYGDBG_DEFINE_CHECK_THIS \
|
262 |
|
|
bool check_this( cyg_assert_class_zeal zeal ) const;
|
263 |
|
|
|
264 |
|
|
#endif // __cplusplus
|
265 |
|
|
|
266 |
|
|
// -------------------------------------------------------------------------
|
267 |
|
|
// Some alternative names for basic assertions that we can disable
|
268 |
|
|
// individually.
|
269 |
|
|
//
|
270 |
|
|
// CYG_PRECONDITION - argument checking etc
|
271 |
|
|
// CYG_POSTCONDITION - results etc
|
272 |
|
|
// CYG_LOOP_INVARIANT - for putting in loops
|
273 |
|
|
//
|
274 |
|
|
// C++ programmers have class-related variants of all of these.
|
275 |
|
|
|
276 |
|
|
#ifdef CYGDBG_INFRA_DEBUG_PRECONDITIONS
|
277 |
|
|
# define CYG_PRECONDITION( _bool_ , _msg_ ) CYG_ASSERT( _bool_, _msg_ )
|
278 |
|
|
# define CYG_PRECONDITIONC( _bool_ ) \
|
279 |
|
|
CYG_ASSERT( _bool_, "precondition " #_bool_)
|
280 |
|
|
#else
|
281 |
|
|
# define CYG_PRECONDITION( _bool_ , _msg_ ) CYG_EMPTY_STATEMENT
|
282 |
|
|
# define CYG_PRECONDITIONC( _bool_ ) CYG_EMPTY_STATEMENT
|
283 |
|
|
#endif
|
284 |
|
|
|
285 |
|
|
#ifdef CYGDBG_INFRA_DEBUG_POSTCONDITIONS
|
286 |
|
|
# define CYG_POSTCONDITION( _bool_ , _msg_ ) CYG_ASSERT( _bool_, _msg_ )
|
287 |
|
|
# define CYG_POSTCONDITIONC( _bool_ ) \
|
288 |
|
|
CYG_ASSERT( _bool_, "postcondition " #_bool_)
|
289 |
|
|
#else
|
290 |
|
|
# define CYG_POSTCONDITION( _bool_ , _msg_ ) CYG_EMPTY_STATEMENT
|
291 |
|
|
# define CYG_POSTCONDITIONC( _bool_ ) CYG_EMPTY_STATEMENT
|
292 |
|
|
#endif
|
293 |
|
|
|
294 |
|
|
#ifdef CYGDBG_INFRA_DEBUG_LOOP_INVARIANTS
|
295 |
|
|
# define CYG_LOOP_INVARIANT( _bool_ , _msg_ ) CYG_ASSERT( _bool_, _msg_ )
|
296 |
|
|
# define CYG_LOOP_INVARIANTC( _bool_ ) \
|
297 |
|
|
CYG_ASSERT( _bool_, "loop invariant " #_bool_ )
|
298 |
|
|
#else
|
299 |
|
|
# define CYG_LOOP_INVARIANT( _bool_ , _msg_ ) CYG_EMPTY_STATEMENT
|
300 |
|
|
# define CYG_LOOP_INVARIANTC( _bool_ ) CYG_EMPTY_STATEMENT
|
301 |
|
|
#endif
|
302 |
|
|
|
303 |
|
|
#ifdef __cplusplus
|
304 |
|
|
|
305 |
|
|
// All variants of _CLASS
|
306 |
|
|
# define CYG_PRECONDITION_CLASS( _pobj_, _msg_ ) \
|
307 |
|
|
CYG_PRECONDITION( ((0 != (_pobj_)) && \
|
308 |
|
|
(_pobj_)->check_this(CYG_ASSERT_CLASS_ZEAL)), _msg_)
|
309 |
|
|
|
310 |
|
|
# define CYG_PRECONDITION_CLASSC( _pobj_ ) \
|
311 |
|
|
CYG_PRECONDITION_CLASS( (_pobj_), \
|
312 |
|
|
"precondition, class pointer (" #_pobj_ ") is valid" )
|
313 |
|
|
|
314 |
|
|
# define CYG_POSTCONDITION_CLASS( _pobj_, _msg_ ) \
|
315 |
|
|
CYG_POSTCONDITION( ((0 != (_pobj_)) && \
|
316 |
|
|
(_pobj_)->check_this(CYG_ASSERT_CLASS_ZEAL)), _msg_)
|
317 |
|
|
|
318 |
|
|
# define CYG_POSTCONDITION_CLASSC( _pobj_ ) \
|
319 |
|
|
CYG_POSTCONDITION_CLASS( (_pobj_), \
|
320 |
|
|
"postcondition, class pointer (" #_pobj_ ") is valid" )
|
321 |
|
|
|
322 |
|
|
# define CYG_LOOP_INVARIANT_CLASS( _pobj_, _msg_) \
|
323 |
|
|
CYG_LOOP_INVARIANT( ((0 != (_pobj_)) && \
|
324 |
|
|
(_pobj_)->check_this(CYG_ASSERT_CLASS_ZEAL)), _msg_)
|
325 |
|
|
|
326 |
|
|
# define CYG_LOOP_INVARIANT_CLASSC( _pobj_ ) \
|
327 |
|
|
CYG_LOOP_INVARIANT_CLASS( (_pobj_), \
|
328 |
|
|
"loop invariant, class pointer (" #_pobj_ ") is valid" )
|
329 |
|
|
|
330 |
|
|
// All variants of _CLASSO
|
331 |
|
|
# define CYG_PRECONDITION_CLASSO( _obj_, _msg_ ) \
|
332 |
|
|
CYG_PRECONDITION( (_obj_).check_this(CYG_ASSERT_CLASS_ZEAL), _msg_)
|
333 |
|
|
|
334 |
|
|
# define CYG_PRECONDITION_CLASSOC( _obj_ ) \
|
335 |
|
|
CYG_PRECONDITION_CLASSO( (_obj_), \
|
336 |
|
|
"precondition, object (" #_obj_ ") is valid" )
|
337 |
|
|
|
338 |
|
|
# define CYG_POSTCONDITION_CLASSO( _obj_, _msg_ ) \
|
339 |
|
|
CYG_POSTCONDITION( (_obj_).check_this(CYG_ASSERT_CLASS_ZEAL), _msg_)
|
340 |
|
|
|
341 |
|
|
# define CYG_POSTCONDITION_CLASSOC( _obj_ ) \
|
342 |
|
|
CYG_POSTCONDITION_CLASSO( (_obj_), \
|
343 |
|
|
"postcondition, object (" #_obj_ ") is valid" )
|
344 |
|
|
|
345 |
|
|
# define CYG_LOOP_INVARIANT_CLASSO( _obj_, _msg_) \
|
346 |
|
|
CYG_LOOP_INVARIANT( (_obj_).check_this(CYG_ASSERT_CLASS_ZEAL), _msg_)
|
347 |
|
|
|
348 |
|
|
# define CYG_LOOP_INVARIANT_CLASSOC( _obj_ ) \
|
349 |
|
|
CYG_LOOP_INVARIANT_CLASSO( (_obj_), \
|
350 |
|
|
"loop invariant, object (" #_obj_ ") is valid" )
|
351 |
|
|
|
352 |
|
|
// All variants of _ZERO_OR_CLASS
|
353 |
|
|
# define CYG_PRECONDITION_ZERO_OR_CLASS( _pobj_, _msg_ ) \
|
354 |
|
|
CYG_PRECONDITION( ((0 == (_pobj_)) || \
|
355 |
|
|
(_pobj_)->check_this(CYG_ASSERT_CLASS_ZEAL)), _msg_)
|
356 |
|
|
|
357 |
|
|
# define CYG_PRECONDITION_ZERO_OR_CLASSC( _pobj_ ) \
|
358 |
|
|
CYG_PRECONDITION_ZERO_OR_CLASS( (_pobj_), \
|
359 |
|
|
"precondition, class pointer (" #_pobj_ ") is zero or valid" )
|
360 |
|
|
|
361 |
|
|
# define CYG_POSTCONDITION_ZERO_OR_CLASS( _pobj_, _msg_ ) \
|
362 |
|
|
CYG_POSTCONDITION( ((0 == (_pobj_)) || \
|
363 |
|
|
(_pobj_)->check_this(CYG_ASSERT_CLASS_ZEAL)), _msg_)
|
364 |
|
|
|
365 |
|
|
# define CYG_POSTCONDITION_ZERO_OR_CLASSC( _pobj_ ) \
|
366 |
|
|
CYG_POSTCONDITION_ZERO_OR_CLASS( (_pobj_), \
|
367 |
|
|
"postcondition, class pointer (" #_pobj_ ") is zero or valid" )
|
368 |
|
|
|
369 |
|
|
# define CYG_LOOP_INVARIANT_ZERO_OR_CLASS( _pobj_, _msg_) \
|
370 |
|
|
CYG_LOOP_INVARIANT( ((0 == (_pobj_)) || \
|
371 |
|
|
(_pobj_)->check_this(CYG_ASSERT_CLASS_ZEAL)), _msg_)
|
372 |
|
|
|
373 |
|
|
# define CYG_LOOP_INVARIANT_ZERO_OR_CLASSC( _pobj_ ) \
|
374 |
|
|
CYG_LOOP_INVARIANT_ZERO_OR_CLASS( (_pobj_), \
|
375 |
|
|
"loop invariant, class pointer (" #_pobj_ ") is zero or valid" )
|
376 |
|
|
|
377 |
|
|
// All variants of _THIS
|
378 |
|
|
# define CYG_PRECONDITION_THIS( _msg_ ) \
|
379 |
|
|
CYG_PRECONDITION( this->check_this(CYG_ASSERT_CLASS_ZEAL), _msg_)
|
380 |
|
|
|
381 |
|
|
# define CYG_PRECONDITION_THISC() \
|
382 |
|
|
CYG_PRECONDITION_THIS( "precondition, \"this\" is valid" )
|
383 |
|
|
|
384 |
|
|
# define CYG_POSTCONDITION_THIS( _msg_ ) \
|
385 |
|
|
CYG_POSTCONDITION( this->check_this(CYG_ASSERT_CLASS_ZEAL), _msg_)
|
386 |
|
|
|
387 |
|
|
# define CYG_POSTCONDITION_THISC() \
|
388 |
|
|
CYG_POSTCONDITION_THIS( "postcondition, \"this\" is valid" )
|
389 |
|
|
|
390 |
|
|
# define CYG_LOOP_INVARIANT_THIS( _msg_) \
|
391 |
|
|
CYG_LOOP_INVARIANT( this->check_this(CYG_ASSERT_CLASS_ZEAL), _msg_)
|
392 |
|
|
|
393 |
|
|
# define CYG_LOOP_INVARIANT_THISC() \
|
394 |
|
|
CYG_LOOP_INVARIANT_THIS( "loop invariant, \"this\" is valid" )
|
395 |
|
|
|
396 |
|
|
#endif // __cplusplus
|
397 |
|
|
|
398 |
|
|
// -------------------------------------------------------------------------
|
399 |
|
|
// Invariants. These are a bit more interesting. The ordinary invariants
|
400 |
|
|
// take an arbitrary boolean expression, and C++ does not provide any way
|
401 |
|
|
// of evaluating this expression automatically on entry and exit - any
|
402 |
|
|
// attempt to use local objects leads to trying to evaluate the expression
|
403 |
|
|
// when it is not in scope. This problem does not arise with objects.
|
404 |
|
|
//
|
405 |
|
|
// For C++ objects it is possible to do a bit better. A template can be
|
406 |
|
|
// used to create a local object whose constructor will validate the
|
407 |
|
|
// target object and whose destructor will validate the target object
|
408 |
|
|
// again. Unfortunately it is necessary to pass the type as well as
|
409 |
|
|
// the object: typeof() is a gcc extension, and RTTI's typeid facility
|
410 |
|
|
// would provide the derived class and not what we actually want.
|
411 |
|
|
|
412 |
|
|
#ifdef CYGDBG_INFRA_DEBUG_INVARIANTS
|
413 |
|
|
|
414 |
|
|
# define CYG_INVARIANT( _bool_, _msg_ ) \
|
415 |
|
|
CYG_MACRO_START \
|
416 |
|
|
if ( ! ( _bool_ ) ) \
|
417 |
|
|
CYG_ASSERT_DOCALL( _msg_ ); \
|
418 |
|
|
CYG_MACRO_END
|
419 |
|
|
|
420 |
|
|
# define CYG_INVARIANTC( _bool_ ) \
|
421 |
|
|
CYG_MACRO_START \
|
422 |
|
|
if ( ! ( _bool_ ) ) \
|
423 |
|
|
CYG_ASSERT_DOCALL( "invariant (" #_bool_ ")" ); \
|
424 |
|
|
CYG_MACRO_END
|
425 |
|
|
|
426 |
|
|
# ifdef __cplusplus
|
427 |
|
|
// NOTE: if the compiler does not manage to inline the appropriate
|
428 |
|
|
// template functions then the impact on code size and performance becomes
|
429 |
|
|
// rather large. But there are significant performance overheads anyway
|
430 |
|
|
// simply because of the call to check_this()...
|
431 |
|
|
//
|
432 |
|
|
template<class X> class __CygInvariantObject {
|
433 |
|
|
|
434 |
|
|
const X* rep;
|
435 |
|
|
|
436 |
|
|
private:
|
437 |
|
|
// Prevent access to the default constructors.
|
438 |
|
|
__CygInvariantObject() { }
|
439 |
|
|
__CygInvariantObject( const __CygInvariantObject& arg ) { }
|
440 |
|
|
__CygInvariantObject & operator=( const __CygInvariantObject & arg) { return *this; }
|
441 |
|
|
|
442 |
|
|
public:
|
443 |
|
|
__CygInvariantObject( X* arg, const char* msg ) : rep(arg) {
|
444 |
|
|
if ( !rep->check_this( CYG_ASSERT_CLASS_ZEAL ) )
|
445 |
|
|
CYG_ASSERT_DOCALL( msg );
|
446 |
|
|
}
|
447 |
|
|
__CygInvariantObject( X& arg, const char* msg ) : rep(&arg) {
|
448 |
|
|
if ( !rep->check_this( CYG_ASSERT_CLASS_ZEAL ) )
|
449 |
|
|
CYG_ASSERT_DOCALL( msg );
|
450 |
|
|
}
|
451 |
|
|
__CygInvariantObject( const X* arg, const char* msg ) : rep(arg) {
|
452 |
|
|
if ( !rep->check_this( CYG_ASSERT_CLASS_ZEAL ) )
|
453 |
|
|
CYG_ASSERT_DOCALL( msg );
|
454 |
|
|
}
|
455 |
|
|
__CygInvariantObject( const X& arg, const char* msg ) : rep(&arg) {
|
456 |
|
|
if ( !rep->check_this( CYG_ASSERT_CLASS_ZEAL ) )
|
457 |
|
|
CYG_ASSERT_DOCALL( msg );
|
458 |
|
|
}
|
459 |
|
|
~__CygInvariantObject( ) {
|
460 |
|
|
if ( !rep->check_this( CYG_ASSERT_CLASS_ZEAL ) )
|
461 |
|
|
CYG_ASSERT_DOCALL( "invariant, object valid on exit" );
|
462 |
|
|
rep = 0;
|
463 |
|
|
};
|
464 |
|
|
};
|
465 |
|
|
|
466 |
|
|
//
|
467 |
|
|
// These macros provide sensible concatenation facilities at
|
468 |
|
|
// the C preprocessor level, getting around complications in the
|
469 |
|
|
// macro expansion rules related to __LINE__ and __FILE__.
|
470 |
|
|
|
471 |
|
|
# define __CYG_INVARIANT_CLASSNAME_AUX( a, b) a ## b
|
472 |
|
|
# define __CYG_INVARIANT_CLASSNAME( a, b ) \
|
473 |
|
|
__CYG_INVARIANT_CLASSNAME_AUX( a, b )
|
474 |
|
|
|
475 |
|
|
|
476 |
|
|
// These macro definitions do not use CYG_MACRO_START because
|
477 |
|
|
// I do not want the scope of the local objects to get confused.
|
478 |
|
|
//
|
479 |
|
|
// The first line of the macro expansion specifies the type of
|
480 |
|
|
// the local object being created. The second line invents a
|
481 |
|
|
// name for this object. The third line provides command-line
|
482 |
|
|
// arguments.
|
483 |
|
|
|
484 |
|
|
# define CYG_INVARIANT_CLASS( _type_, _pobj_, _msg_ ) \
|
485 |
|
|
__CygInvariantObject<_type_> \
|
486 |
|
|
__CYG_INVARIANT_CLASSNAME( __invariant_class_, __LINE__ ) \
|
487 |
|
|
( _pobj_, _msg_ )
|
488 |
|
|
|
489 |
|
|
# define CYG_INVARIANT_CLASSC( _type_, _pobj_ ) \
|
490 |
|
|
__CygInvariantObject<_type_> \
|
491 |
|
|
__CYG_INVARIANT_CLASSNAME( __invariant_class_, __LINE__ ) \
|
492 |
|
|
( _pobj_, "invariant, class pointer (" #_pobj_ ") is valid" )
|
493 |
|
|
|
494 |
|
|
# define CYG_INVARIANT_CLASSO( _type_, _obj_, _msg_ ) \
|
495 |
|
|
__CygInvariantObject<_type_> \
|
496 |
|
|
__CYG_INVARIANT_CLASSNAME( __invariant_class_, __LINE__ ) \
|
497 |
|
|
( _obj_, _msg_ )
|
498 |
|
|
|
499 |
|
|
# define CYG_INVARIANT_CLASSOC( _type_, _obj_ ) \
|
500 |
|
|
__CygInvariantObject<_type_> \
|
501 |
|
|
__CYG_INVARIANT_CLASSNAME( __invariant_class_, __LINE__ ) \
|
502 |
|
|
( _obj_, "invariant, object (" #_obj_ ") is valid" )
|
503 |
|
|
|
504 |
|
|
# define CYG_INVARIANT_THIS( _type_, _msg_ ) \
|
505 |
|
|
__CygInvariantObject<_type_> \
|
506 |
|
|
__CYG_INVARIANT_CLASSNAME( __invariant_class_, __LINE__ ) \
|
507 |
|
|
( this, _msg_ )
|
508 |
|
|
|
509 |
|
|
# define CYG_INVARIANT_THISC( _type_ ) \
|
510 |
|
|
__CygInvariantObject<_type_> \
|
511 |
|
|
__CYG_INVARIANT_CLASSNAME( __invariant_class_, __LINE__ ) \
|
512 |
|
|
( this, "invariant, \"this\" is valid" )
|
513 |
|
|
|
514 |
|
|
# endif // __cplusplus
|
515 |
|
|
|
516 |
|
|
#else // !CYGDBG_INFRA_DEBUG_INVARIANTS
|
517 |
|
|
|
518 |
|
|
# define CYG_INVARIANT( _bool_, _msg_ ) CYG_EMPTY_STATEMENT
|
519 |
|
|
# define CYG_INVARIANTC( _bool_ ) CYG_EMPTY_STATEMENT
|
520 |
|
|
|
521 |
|
|
# ifdef __cplusplus
|
522 |
|
|
|
523 |
|
|
# define CYG_INVARIANT_CLASS( _type_, _pobj_, _msg_ )
|
524 |
|
|
# define CYG_INVARIANT_CLASSC( _type_, _pobj_ )
|
525 |
|
|
# define CYG_INVARIANT_CLASSO( _type_, _obj_, _msg_ )
|
526 |
|
|
# define CYG_INVARIANT_CLASSOC( _type_, _obj_ )
|
527 |
|
|
# define CYG_INVARIANT_THIS( _type_, _msg_ )
|
528 |
|
|
# define CYG_INVARIANT_THISC( _type_ )
|
529 |
|
|
|
530 |
|
|
# endif
|
531 |
|
|
|
532 |
|
|
#endif // CYGDBG_INFRA_DEBUG_INVARIANTS
|
533 |
|
|
|
534 |
|
|
// -------------------------------------------------------------------------
|
535 |
|
|
// Compile time failure; like #error but in a macro so we can use it in
|
536 |
|
|
// other definitions.
|
537 |
|
|
//
|
538 |
|
|
// Usage:
|
539 |
|
|
// #define new CYG_COMPILETIMEFAIL( "Do NOT use new!")
|
540 |
|
|
|
541 |
|
|
#define CYG_COMPILETIMEFAIL( _msg_ ) !!!-- _msg_ --!!!
|
542 |
|
|
|
543 |
|
|
|
544 |
|
|
// -------------------------------------------------------------------------
|
545 |
|
|
// The host-side implementation of the infrastructure provides a number
|
546 |
|
|
// of additional functions that allow applications to provide their own
|
547 |
|
|
// implementation of cyg_assert_fail(). This is not strictly necessary
|
548 |
|
|
// since the presence of cyg_assert_fail() in the application would
|
549 |
|
|
// override the one in the library anyway, but it is useful to make
|
550 |
|
|
// certain functionality more readily available.
|
551 |
|
|
//
|
552 |
|
|
// These declarations are only available if the symbol
|
553 |
|
|
// CYG_DECLARE_HOST_ASSERTION_SUPPORT is defined.
|
554 |
|
|
#ifdef CYG_DECLARE_HOST_ASSERTION_SUPPORT
|
555 |
|
|
|
556 |
|
|
// The default assertion handler writes its output to a file and
|
557 |
|
|
// if possible a suitable message to stdout. It is possible to
|
558 |
|
|
// install an alternative handler. If this alternative returns false
|
559 |
|
|
// then the default handler will be invoked instead, otherwise the
|
560 |
|
|
// application will exit.
|
561 |
|
|
externC void cyg_assert_install_failure_handler(
|
562 |
|
|
bool (*)(const char* /* psz_func */,
|
563 |
|
|
const char* /* psz_file */,
|
564 |
|
|
cyg_uint32 /* linenum */,
|
565 |
|
|
const char* /* psz_msg */) );
|
566 |
|
|
|
567 |
|
|
// Register a callback that should get invoked as part of handling an
|
568 |
|
|
// assertion failure and that will typically produce some additional
|
569 |
|
|
// output. For example the trace code will install a callback to output
|
570 |
|
|
// trace information.
|
571 |
|
|
//
|
572 |
|
|
// The first argument is a string identifying the callback. The second
|
573 |
|
|
// argument is a function pointer for the callback itself, whose
|
574 |
|
|
// argument is another function that can be invoked for output.
|
575 |
|
|
externC void cyg_assert_install_failure_callback(
|
576 |
|
|
const char* /* name */,
|
577 |
|
|
void (*)( void (*)(const char*) ));
|
578 |
|
|
|
579 |
|
|
// This function can be called by assert failure handlers to invoke
|
580 |
|
|
// the installed callbacks. The three arguments are function pointers
|
581 |
|
|
// that get invoked prior to callback invocation, by the callback itself,
|
582 |
|
|
// and after each callback. In the first case the argument will be the
|
583 |
|
|
// callback name.
|
584 |
|
|
externC void cyg_assert_failure_invoke_callbacks(
|
585 |
|
|
void (*)(const char* /* name */),
|
586 |
|
|
void (*)(const char* /* callback data */ ),
|
587 |
|
|
void (*)(void) );
|
588 |
|
|
|
589 |
|
|
// This function is intended to be called from inside gdb instead of
|
590 |
|
|
// cyg_assert_fail(),, without the need to specify a filename or
|
591 |
|
|
// anything else.
|
592 |
|
|
externC void cyg_assert_quickfail(void);
|
593 |
|
|
|
594 |
|
|
#endif // CYG_DECLARE_HOST_ASSERTION_SUPPORT
|
595 |
|
|
|
596 |
|
|
// -------------------------------------------------------------------------
|
597 |
|
|
|
598 |
|
|
#endif // CYGONCE_INFRA_CYG_ASS_H multiple inclusion protection
|
599 |
|
|
// EOF cyg_ass.h
|