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