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