1 2 3 4 5 6 7 8 9 10 11 12
13 14 15 16 17 18 19
20
21 /*!
22 * ======== Assert ========
23 * Runtime assertion manager
24 *
25 * The `Assert` module provides configurable diagnostics to the program.
26 * Similar to the standard C `assert()` macro, `Assert` methods are
27 * interspersed with other code to add diagnostics to a program. Unlike
28 * the standard C assert support, the `Assert` module provides greater
29 * flexibility in managing the messages displayed, the message string
30 * space overhead, and the runtime handling of failures. In addition,
31 * because the `Assert` methods build atop the Diags module, you can
32 * precisely control which asserts remain in the final application, if any.
33 *
34 * The `Assert` module works in conjunction with the `{@link Diags}` module.
35 * `Assert` statements are added to the code using the
36 * `{@link #isTrue Assert_isTrue()}` function. Execution of assert
37 * statements is controlled by the `{@link Diags#ASSERT}` and
38 * `{@link Diags#INTERNAL}` bits in a module's diagnostics mask. By default,
39 * all module's `Diags_ASSERT` bit is enabled and the `Diags_INTERNAL` bit
40 * is disabled. See `{@link Types#Common$ Types.Common$}` for the
41 * declaration of the bits in the diagnostics mask and
42 * `{@link Defaults#common$ Default.common$}` for the default module settings.
43 *
44 * Two types of asserts are supported: public asserts and internal asserts.
45 *
46 * @p(blist)
47 * - Public asserts have an assert ID and are, by default, controlled
48 * by the `{@link Diags#ASSERT}` bit.
49 * - Internal asserts don't have an assert ID (other than NULL) and
50 * are active only when both the `{@link Diags#ASSERT}` and
51 * `{@link Diags#INTERNAL}` bits of the module's diagnostics mask are set.
52 * @p
53 *
54 * `Assert` IDs are small integer values that index into a table of
55 * assertion descriptors. These descriptors hold an error message
56 * and a diagnostics mask that is used to enable and disable the
57 * assertion at runtime.
58 *
59 * You can remap individual public asserts to different bits in the
60 * diagnostics mask, or can disable the assert altogether. This is
61 * done by setting the mask property of the assert ID. Setting the
62 * mask to 0 disables the assert. In all other cases, the `Diags.ASSERT`
63 * bit is OR'd together with the mask to define the controlling bits.
64 * For example, the module's diagnostics mask must have the `Diags.ASSERT`
65 * bit set and any other bit specified in the mask property of the
66 * assert ID in order to activate the assert.
67 *
68 * @a(Examples)
69 * Example 1: The following C code adds an assert to application code
70 * which is not in a module. This assert does not have an assert
71 * identifier (the second argument is NULL); this makes it an internal
72 * assert.
73 *
74 * @p(code)
75 * // file.c
76 * #include <xdc/runtime/Assert.h>
77 *
78 * Assert_isTrue(count > 0, NULL);
79 * @p
80 *
81 * The following XDC configuration statements set both the ASSERT and
82 * INTERNAL bits in the diagnostics mask to enable the internal assert
83 * created in the previous C code. Since the C code is not in a module,
84 * you must set the bits in the diagnostics mask of the
85 * `{@link xdc.runtime.Main xdc.runtime.Main}` module. The Main module
86 * is used to control all `{@link Log}` and `Assert` statements that are
87 * not part of the implementation of a module; for example, top-level
88 * application code or any existing sources that simply call the `Log` or
89 * `Assert` methods.
90 *
91 * @p(code)
92 * // program.cfg
93 * var Assert = xdc.useModule('xdc.runtime.Assert');
94 * var Diags = xdc.useModule('xdc.runtime.Diags');
95 * var Main = xdc.useModule('xdc.runtime.Main');
96 *
97 * Main.common$.diags_ASSERT = Diags.ALWAYS_ON;
98 * Main.common$.diags_INTERNAL = Diags.ALWAYS_ON;
99 * @p
100 *
101 * @p(html)
102 * <hr />
103 * @p
104 *
105 * Example 2: The following example shows how to use and configure an
106 * assert ID that is declared by a module. It adds that assert to the
107 * application's C source code, and configures the application to
108 * execute the assert.
109 *
110 * This is part of the XDC file for the module that declares an `Assert` Id:
111 *
112 * @p(code)
113 * // Mod.xdc
114 * import xdc.runtime.Assert;
115 * import xdc.runtime.Diags;
116 *
117 * config Assert.Id A_nonZero = {
118 * msg: "A_nonZero: value must be non-zero"
119 * };
120 * @p
121 *
122 * This is part of the C code for the application:
123 *
124 * @p(code)
125 * // Mod.c
126 * #include <xdc/runtime/Assert.h>
127 *
128 * Assert_isTrue(x != 0, Mod_A_nonZero);
129 * @p
130 *
131 * This is part of the XDC configuration file for the application:
132 *
133 * @p(code)
134 * // program.cfg
135 * var Diags = xdc.useModule('xdc.runtime.Diags');
136 * var Mod = xdc.useModule('my.pkg.Mod');
137 * Mod.common$.diags_ASSERT = Diags.ALWAYS_ON;
138 * @p
139 */
140
141 @CustomHeader
142
143 module Assert {
144
145 /*!
146 * ======== Assert_Desc ========
147 * Assert descriptor
148 *
149 * Each public assert is defined with an assert descriptor. This
150 * structure defines which bits in the module's diagnostics mask
151 * control this assert, and the message raised when the assert fails.
152 * The mask property is optional, it defaults to the
153 * `{@link Diags#ASSERT}` bit.
154 *
155 * @field(mask) Specifies which bits enable the assert.
156 * @field(msg) The message printed when the assert fails.
157 */
158 metaonly struct Desc {
159 Diags.Mask mask;
160 String msg;
161 };
162
163 /*!
164 * ======== Assert_Id ========
165 * Assert identifier
166 *
167 * Each metaonly assert descriptor is encoded into a target accessable
168 * assert Id type which can be passed to the `{@link #isTrue}` function.
169 */
170 @Encoded typedef Desc Id;
171
172 /*!
173 * ======== E_assertFailed ========
174 * The `{@link Error#Id}` raised when an assertion violation is detected
175 *
176 * When an assertion violation is triggered, an error is raised via
177 * `Error_raise()`. `E_assert_Failed` is the `{@link Error#Id}` passed
178 * to `Error_raise()`.
179 *
180 * The first string argument (%s) will be either "", if the assertion Id
181 * is `NULL` (for internal asserts), or ": " (for public asserts).
182 * The second string argument (%s) is the
183 * `Assert.Desc.msg` string associated with the assertion Id; if the
184 * Id is `NULL` (an internal assert) or if text is not loaded
185 * (`!{@link Text#isLoaded}()`), this string is "".
186 *
187 * @see #isTrue
188 * @see Error#Id
189 */
190 readonly config Error.Id E_assertFailed = {msg: "assertion failure%s%s"};
191
192 /*!
193 * ======== Assert_isTrue ========
194 * Test an assertion
195 *
196 * `Assert_isTrue()` statements may be conditionally enabled (disabled)
197 * on a per module basis by setting the calling module's
198 * `{@link IModule#$common $common.diags_ASSERT}` configuration
199 * parameter. If
200 * the `Assert_isTrue()` statement is not in a module, the calling
201 * module is the `{@link Main}` module. You must enable the
202 * `{@link Diags#ASSERT}` bit in the module's diagnostics mask for this
203 * call to be enabled. If a `NULL` assert id is specified, then you
204 * must enable the `{@link Diags#INTERNAL}` in addition to the
205 * `ASSERT` bit.
206 *
207 * If the `Assert_isTrue()` statement is enabled and `expr` evaluates to
208 * false, the assert specified by `id` is raised; i.e., the
209 * `{@link #E_assertFailed}` error is raised with a `NULL`
210 * error block. In other words, the standard `{@link Error#raise}`
211 * handling hooks will be run, `{@link System#abort()}` will be called,
212 * and control does not return to the caller. The `id` may be `null`, in
213 * which case you will get a generic assert message.
214 *
215 * @param(expr) the expression which should evaluate to true
216 * @param(id) identifies the assert being raised
217 *
218 * @a(Examples)
219 * C Code
220 * @p(code)
221 * #include <xdc/runtime/Assert.h>
222 *
223 * Assert_isTrue(count > 0, NULL);
224 * @p
225 */
226 @Macro Void isTrue(Bool expr, Id id);
227
228 internal:
229
230 Void raise(Types.ModuleId mod, String file, Int line, Id id);
231
232 }
233 234 235
236