-
Notifications
You must be signed in to change notification settings - Fork 163
/
Copy pathqassert.h
397 lines (369 loc) · 13.9 KB
/
qassert.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
/*$file${include::qassert.h} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
/*
* Model: qpc.qm
* File: ${include::qassert.h}
*
* This code has been generated by QM 5.2.5 <www.state-machine.com/qm>.
* DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
*
* This code is covered by the following QP license:
* License # : LicenseRef-QL-dual
* Issued to : Any user of the QP/C real-time embedded framework
* Framework(s) : qpc
* Support ends : 2023-12-31
* License scope:
*
* Copyright (C) 2005 Quantum Leaps, LLC <state-machine.com>.
*
* SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
*
* This software is dual-licensed under the terms of the open source GNU
* General Public License version 3 (or any later version), or alternatively,
* under the terms of one of the closed source Quantum Leaps commercial
* licenses.
*
* The terms of the open source GNU General Public License version 3
* can be found at: <www.gnu.org/licenses/gpl-3.0>
*
* The terms of the closed source Quantum Leaps commercial licenses
* can be found at: <www.state-machine.com/licensing>
*
* Redistributions in source code must retain this top-level comment block.
* Plagiarizing this software to sidestep the license obligations is illegal.
*
* Contact information:
* <www.state-machine.com/licensing>
* <info@state-machine.com>
*/
/*$endhead${include::qassert.h} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
/*! @file
* @brief Customizable and memory-efficient Design by Contract (DbC)
* for embedded systems
*
* @note
* This header file can be used in C, C++, and mixed C/C++ programs.
*
* @note
* The preprocessor switch #Q_NASSERT disables checking assertions.
* However, it is generally **not** advisable to disable assertions,
* **especially** in the production code. Instead, the assertion
* handler Q_onAssert() should be very carefully designed and tested.
*/
#ifndef QASSERT_H_
#define QASSERT_H_
#ifdef __cplusplus
extern "C" {
#endif
#ifndef Q_NASSERT
/*$declare${DbC::active} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
/*${DbC::active::Q_DEFINE_THIS_MODULE} .....................................*/
/*! Define the user-specified module name for assertions in this file.
*
* @details
* Macro to be placed at the top of each C/C++ module to define the
* single instance of the module name string to be used in reporting
* assertions in this module. This macro takes the user-supplied parameter
* `name_` instead of `__FILE__` to precisely control the name of the
* module.
*
* @param[in] name_ string constant representing the module name
*
* @note
* This macro should **not** be terminated by a semicolon.
*/
#define Q_DEFINE_THIS_MODULE(name_) \
static char const Q_this_module_[] = name_;
/*${DbC::active::Q_ASSERT_ID} ..............................................*/
#ifndef Q_NASSERT
/*! General-purpose assertion with user-specified ID number.
*
* @details
* Evaluates the Boolean expression `expr_` and does nothing else when
* it evaluates to 'true'. However, when `expr_` evaluates to 'false',
* the Q_ASSERT_ID() macro calls the no-return function Q_onAssert().
*
* @param[in] id_ ID number (unique within the module) of the assertion
* @param[in] expr_ Boolean expression to check
*
* @attention
* When assertions are disabled (by defining the ::Q_NASSERT macro), the
* Q_ASSERT_ID() macro expands to nothing, and consequently the Boolean
* expression `expr_` is **not** evaluated and the callback function
* Q_onAssert() is **not** called.
*/
#define Q_ASSERT_ID(id_, expr_) ((expr_) \
? ((void)0) : Q_onAssert(&Q_this_module_[0], (id_)))
#endif /* ndef Q_NASSERT */
/*${DbC::active::Q_ERROR_ID} ...............................................*/
/*! Assertion with user-specified ID for a wrong path through the code
*
* @details
* Calls the Q_onAssert() callback if ever executed. This assertion
* takes the user-supplied parameter `id_` to identify the location of
* this assertion within the file. This avoids the volatility of using
* line numbers, which change whenever a line of code is added or removed
* upstream from the assertion.
*
* @param[in] id_ ID number (unique within the module) of the assertion
*
* @note
* Does noting if assertions are disabled with the ::Q_NASSERT switch.
*/
#define Q_ERROR_ID(id_) Q_onAssert(&Q_this_module_[0], (id_))
/*${DbC::active::Q_ALLEGE_ID} ..............................................*/
/*! General purpose assertion with user-specified ID number that
* **always** evaluates the `expr_` expression.
*
* @details
* Like the Q_ASSERT_ID() macro, except it **always** evaluates the
* `expr_` expression even when assertions are disabled with the
* ::Q_NASSERT macro. However, when the ::Q_NASSERT macro is defined, the
* Q_onAssert() callback is **not** called, even if `expr_` evaluates
* to FALSE.
*
* @param[in] id_ ID number (unique within the module) of the assertion
* @param[in] expr_ Boolean expression to check
*/
#define Q_ALLEGE_ID(id_, expr_) Q_ASSERT_ID((id_), (expr_))
/*$enddecl${DbC::active} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
#else
/*$declare${DbC::inactive} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
/*${DbC::inactive::Q_DEFINE_THIS_MODULE} ...................................*/
/*! inactive version of Q_DEFINE_THIS_MODULE() */
#define Q_DEFINE_THIS_MODULE(name_)
/*${DbC::inactive::Q_ASSERT_ID} ............................................*/
/*! inactive version of Q_ASSERT_ID() */
#define Q_ASSERT_ID(id_, expr_) ((void)0)
/*${DbC::inactive::Q_ERROR_ID} .............................................*/
/*! inactive version of Q_ERROR_ID() */
#define Q_ERROR_ID(id_) ((void)0)
/*${DbC::inactive::Q_ALLEGE_ID} ............................................*/
/*! inactive version of Q_ALLEGE_ID()
*
* @attention
* The expression `expr_` **is** evaluated, even though assertion
* callback Q_onAssert() is NOT called when `expr_` evaluates to
* false.
*/
#define Q_ALLEGE_ID(id_, expr_) ((void)(expr_))
/*$enddecl${DbC::inactive} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
#endif
/*$declare1${DbC} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
/*${DbC::Q_DEFINE_THIS_FILE} ...............................................*/
/*! Define the file name (with `__FILE__`) for assertions in this file
*
* @details
* Macro to be placed at the top of each C/C++ module to define the
* single instance of the file name string to be used in reporting
* assertions in this module.
*
* @note
* The file name string literal is defined by means of the standard
* preprocessor macro `__FILE__`. However, please note that, depending
* on the compiler, the `__FILE__` macro might contain the whole path name
* to the file, which might be inconvenient to log assertions.
*
* @attention
* This macro should **not** be terminated by a semicolon.
*
* @sa Q_DEFINE_THIS_MODULE()
*/
#define Q_DEFINE_THIS_FILE Q_DEFINE_THIS_MODULE(__FILE__)
/*${DbC::Q_ASSERT} .........................................................*/
/*! General-purpose assertion (with __LINE__ used as location in the file)
*
* @details
* Equivalent to Q_ASSERT_ID(), except it uses __LINE__ to identify the
* assertion within a file.
*
* @param[in] expr_ Boolean expression to check
*
* @sa Q_ASSERT_ID()
*/
#define Q_ASSERT(expr_) Q_ASSERT_ID(__LINE__, (expr_))
/*${DbC::Q_ERROR} ..........................................................*/
/*! Assertion for a wrong path through the code
*
* @details
* Calls the Q_onAssert() callback if ever executed.
*
* @note
* This macro identifies the problem location with the line number,
* which might change as the code is modified.
*
* @sa Q_ERROR_ID()
*/
#define Q_ERROR() Q_ERROR_ID(__LINE__)
/*${DbC::Q_REQUIRE_ID} .....................................................*/
/*! Assertion for checking **preconditions**.
*
* @details
* Equivalent to Q_ASSERT_ID(), except the name provides a better
* documentation of the intention of this assertion.
*
* @param[in] id_ ID number (unique within the module) of the assertion
* @param[in] expr_ Boolean expression
*/
#define Q_REQUIRE_ID(id_, expr_) Q_ASSERT_ID((id_), (expr_))
/*${DbC::Q_REQUIRE} ........................................................*/
/*! Assertion for checking preconditions (based on __LINE__).
*
* @details
* Equivalent to Q_ASSERT(), except the name provides a better documentation
* of the intention of this assertion.
*
* @param[in] expr_ Boolean expression
*/
#define Q_REQUIRE(expr_) Q_ASSERT(expr_)
/*${DbC::Q_ENSURE_ID} ......................................................*/
/*! Assertion for checking postconditions.
*
* @details
* Equivalent to Q_ASSERT_ID(), except the name provides a better documentation
* of the intention of this assertion.
*
* @param[in] id_ ID number (unique within the module) of the assertion
* @param[in] expr_ Boolean expression
*/
#define Q_ENSURE_ID(id_, expr_) Q_ASSERT_ID((id_), (expr_))
/*${DbC::Q_ENSURE} .........................................................*/
/*! Assertion for checking postconditions.
*
* @details
* Equivalent to Q_ASSERT(), except the name provides a better documentation
* of the intention of this assertion.
*
* @param[in] expr_ Boolean expression
*/
#define Q_ENSURE(expr_) Q_ASSERT(expr_)
/*${DbC::Q_INVARIANT_ID} ...................................................*/
/*! Assertion for checking invariants.
*
* @details
* Equivalent to Q_ASSERT_ID(), except the name provides a better
* documentation of the intention of this assertion.
*
* @param[in] id_ ID number (unique within the module) of the assertion
* @param[in] expr_ Boolean expression
*/
#define Q_INVARIANT_ID(id_, expr_) Q_ASSERT_ID((id_), (expr_))
/*${DbC::Q_INVARIANT} ......................................................*/
/*! Assertion for checking invariants.
*
* @details
* Equivalent to Q_ASSERT(), except the name provides a better documentation
* of the intention of this assertion.
*
* @param[in] expr_ Boolean expression
*/
#define Q_INVARIANT(expr_) Q_ASSERT(expr_)
/*${DbC::Q_ALLEGE} .........................................................*/
/*! General purpose assertion with user-specified ID number that
* **always** evaluates the `expr_` expression.
*
* @details
* Equivalent to Q_ALLEGE_ID(), except it identifies the problem location
* with the line number `__LINE__`, which might change as the code is modified.
*
* @param[in] expr_ Boolean expression to check
*
* @sa Q_ALLEGE_ID()
*/
#define Q_ALLEGE(expr_) Q_ALLEGE_ID(__LINE__, (expr_))
/*${DbC::Q_ASSERT_STATIC} ..................................................*/
/*! Static (compile-time) assertion.
*
* @details
* This type of assertion deliberately causes a compile-time error when
* the `expr_` Boolean expression evaluates to FALSE. The macro exploits
* the fact that in C/C++ a dimension of an array cannot be negative.
* The compile-time assertion has no runtime side effects.
*
* @param[in] expr_ Compile-time Boolean expression
*
* @note
* The static assertion macro is provided for backwards compatibility with
* older C standards. Newer C11 supports `_Static_assert()`, which should
* be used instead of Q_ASSERT_STATIC().
*/
#define Q_ASSERT_STATIC(expr_) extern char Q_static_assert_[(expr_) ? 1 : -1]
/*${DbC::Q_NORETURN} .......................................................*/
#ifndef Q_NORETURN
/*! No-return function specifier for the Q_onAssert() callback function.
*
* @details
* If the `Q_NORETURN` macro is undefined, the default definition uses
* the C99 specifier `_Noreturn`.
*
* @note
* The `Q_NORETURN` macro can be defined in the QP port (typically in
* `qep_port.h` or `qep_port.hpp`). If such definition is porvided
* the default won't be used.
*
* @trace
* @tr{PQA01_4}
*/
#define Q_NORETURN _Noreturn void
#endif /* ndef Q_NORETURN */
/*${DbC::int_t} ............................................................*/
#ifndef QP_VERSION
/*! typedef for assertions-ids and line numbers in assertions.
*
* @details
* This typedef specifies integer type for exclusive use in assertions.
* Use of this type, rather than plain 'int', is in compliance
* with the MISRA-C 2012 Dir 4.6 (adv).
*/
typedef int int_t;
#endif /* ndef QP_VERSION */
/*${DbC::Q_onAssert} .......................................................*/
/*! Callback function invoked in case of an assertion failure.
*
* @details
* This callback function needs to be defined in the application to perform
* any corrective action after a non-recoverable error has been detected.
* The Q_onAssert() function is the last line of defense after the
* system failure and its implementation shouild be very **carefully**
* designed and **tested** under various fault conditions, including but
* not limited to: stack overflow, stack corruption, or calling Q_onAssert()
* from an interrupt.
*
* @param[in] module name of the file/module in which the assertion failed
* (constant, zero-terminated C string)
* @param[in] location location of the assertion within the module. This could
* be a line number or a user-specified ID-number.
*
* @returns
* This callback function should **not return** (see ::Q_NORETURN),
* as continuation after an assertion failure does not make sense.
*
* @note
* During debugging, Q_onAssert() is an ideal place to put a breakpoint.
* For deployment, tt is typically a **bad idea** to implement Q_onAssert()
* as an endless loop that ties up the CPU (denial of service).
*
* Called by the following: Q_ASSERT_ID(), Q_ERROR_ID(), Q_REQUIRE_ID(),
* Q_ENSURE_ID(), Q_INVARIANT_ID() and Q_ALLEGE_ID() as well as:
* Q_ASSERT(), Q_ERROR(), Q_REQUIRE(), Q_ENSURE(), Q_INVARIANT(),
* and Q_ALLEGE().
*
* @trace
* @tr{PQA01_4}
*/
Q_NORETURN Q_onAssert(
char const * module,
int_t location);
/*${DbC::Q_DIM} ............................................................*/
#ifndef QP_VERSION
/*! Helper macro to calculate static dimension of a 1-dim `array_`
*
* @param array_ 1-dimensional array
* @returns the length of the array (number of elements it can hold)
*/
#define Q_DIM(array_) (sizeof(array_) / sizeof((array_)[0U]))
#endif /* ndef QP_VERSION */
/*$enddecl${DbC} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
#ifdef __cplusplus
}
#endif
#endif /* QASSERT_H_ */