1 /*
2  * Copyright (c) 2011-2014 Wind River Systems, Inc.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * @file
9  * @brief Debug aid
10  *
11  *
12  * The __ASSERT() macro can be used inside kernel code.
13  *
14  * Assertions are enabled by setting the __ASSERT_ON symbol to a non-zero value.
15  * There are two ways to do this:
16  *   a) Use the ASSERT and ASSERT_LEVEL kconfig options
17  *   b) Add "CFLAGS += -D__ASSERT_ON=<level>" at the end of a project's Makefile
18  * The Makefile method takes precedence over the kconfig option if both are
19  * used.
20  *
21  * Specifying an assertion level of 1 causes the compiler to issue warnings that
22  * the kernel contains debug-type __ASSERT() statements; this reminder is issued
23  * since assertion code is not normally present in a final product. Specifying
24  * assertion level 2 suppresses these warnings.
25  *
26  * The __ASSERT_EVAL() macro can also be used inside kernel code.
27  *
28  * It makes use of the __ASSERT() macro, but has some extra flexibility.  It
29  * allows the developer to specify different actions depending whether the
30  * __ASSERT() macro is enabled or not.  This can be particularly useful to
31  * prevent the compiler from generating comments (errors, warnings or remarks)
32  * about variables that are only used with __ASSERT() being assigned a value,
33  * but otherwise unused when the __ASSERT() macro is disabled.
34  *
35  * Consider the following example:
36  *
37  * int  x;
38  *
39  * x = foo ();
40  * __ASSERT (x != 0, "foo() returned zero!");
41  *
42  * If __ASSERT() is disabled, then 'x' is assigned a value, but never used.
43  * This type of situation can be resolved using the __ASSERT_EVAL() macro.
44  *
45  * __ASSERT_EVAL ((void) foo(),
46  *		  int x = foo(),
47  *                x != 0,
48  *                "foo() returned zero!");
49  *
50  * The first parameter tells __ASSERT_EVAL() what to do if __ASSERT() is
51  * disabled.  The second parameter tells __ASSERT_EVAL() what to do if
52  * __ASSERT() is enabled.  The third and fourth parameters are the parameters
53  * it passes to __ASSERT().
54  *
55  * The __ASSERT_NO_MSG() macro can be used to perform an assertion that reports
56  * the failed test and its location, but lacks additional debugging information
57  * provided to assist the user in diagnosing the problem; its use is
58  * discouraged.
59  */
60 
61 #ifndef ___ASSERT__H_
62 #define ___ASSERT__H_
63 #include <stdio.h>
64 
65 #ifdef CONFIG_ASSERT
66 #ifndef __ASSERT_ON
67 #define __ASSERT_ON CONFIG_ASSERT_LEVEL
68 #endif
69 #endif
70 
71 #ifdef CONFIG_FORCE_NO_ASSERT
72 #undef __ASSERT_ON
73 #define __ASSERT_ON 0
74 #endif
75 
76 #if defined(CONFIG_ASSERT_VERBOSE)
77 #define __ASSERT_PRINT(fmt, ...) printk(fmt, ##__VA_ARGS__)
78 #else /* CONFIG_ASSERT_VERBOSE */
79 #define __ASSERT_PRINT(fmt, ...)
80 #endif /* CONFIG_ASSERT_VERBOSE */
81 
82 #ifdef CONFIG_ASSERT_NO_MSG_INFO
83 #define __ASSERT_MSG_INFO(fmt, ...)
84 #else  /* CONFIG_ASSERT_NO_MSG_INFO */
85 #define __ASSERT_MSG_INFO(fmt, ...) __ASSERT_PRINT("\t" fmt "\n", ##__VA_ARGS__)
86 #endif /* CONFIG_ASSERT_NO_MSG_INFO */
87 
88 #if !defined(CONFIG_ASSERT_NO_COND_INFO) && !defined(CONFIG_ASSERT_NO_FILE_INFO)
89 #define __ASSERT_LOC(test)                              \
90 	__ASSERT_PRINT("ASSERTION FAIL [%s] @ %s:%d\n", \
91 		Z_STRINGIFY(test),                      \
92 		__FILE__, __LINE__)
93 #endif
94 
95 #if defined(CONFIG_ASSERT_NO_COND_INFO) && !defined(CONFIG_ASSERT_NO_FILE_INFO)
96 #define __ASSERT_LOC(test)                         \
97 	__ASSERT_PRINT("ASSERTION FAIL @ %s:%d\n", \
98 		__FILE__, __LINE__)
99 #endif
100 
101 #if !defined(CONFIG_ASSERT_NO_COND_INFO) && defined(CONFIG_ASSERT_NO_FILE_INFO)
102 #define __ASSERT_LOC(test)                      \
103 	__ASSERT_PRINT("ASSERTION FAIL [%s]\n", \
104 		Z_STRINGIFY(test))
105 #endif
106 
107 #if defined(CONFIG_ASSERT_NO_COND_INFO) && defined(CONFIG_ASSERT_NO_FILE_INFO)
108 #define __ASSERT_LOC(test)                 \
109 	__ASSERT_PRINT("ASSERTION FAIL\n")
110 #endif
111 
112 #ifdef __ASSERT_ON
113 #if (__ASSERT_ON < 0) || (__ASSERT_ON > 2)
114 #error "Invalid __ASSERT() level: must be between 0 and 2"
115 #endif
116 
117 #if __ASSERT_ON
118 #include <misc/printk.h>
119 
120 #ifdef __cplusplus
121 extern "C" {
122 #endif
123 
124 #ifdef CONFIG_ASSERT_NO_FILE_INFO
125 void assert_post_action(void);
126 #define __ASSERT_POST_ACTION() assert_post_action()
127 #else  /* CONFIG_ASSERT_NO_FILE_INFO */
128 void assert_post_action(const char *file, unsigned int line);
129 #define __ASSERT_POST_ACTION() assert_post_action(__FILE__, __LINE__)
130 #endif /* CONFIG_ASSERT_NO_FILE_INFO */
131 
132 #ifdef __cplusplus
133 }
134 #endif
135 
136 #define __ASSERT_NO_MSG(test)                                             \
137 	do {                                                              \
138 		if (!(test)) {                                            \
139 			__ASSERT_LOC(test);                               \
140 			__ASSERT_POST_ACTION();                           \
141 		}                                                         \
142 	} while (false)
143 
144 #define __ASSERT(test, fmt, ...)                                          \
145 	do {                                                              \
146 		if (!(test)) {                                            \
147 			__ASSERT_LOC(test);                               \
148 			__ASSERT_MSG_INFO(fmt, ##__VA_ARGS__);            \
149 			__ASSERT_POST_ACTION();                           \
150 		}                                                         \
151 	} while (false)
152 
153 #define __ASSERT_EVAL(expr1, expr2, test, fmt, ...)                \
154 	do {                                                       \
155 		expr2;                                             \
156 		__ASSERT(test, fmt, ##__VA_ARGS__);                \
157 	} while (0)
158 
159 #if (__ASSERT_ON == 1)
160 #warning "__ASSERT() statements are ENABLED"
161 #endif
162 #else
163 #define __ASSERT(test, fmt, ...) { }
164 #define __ASSERT_EVAL(expr1, expr2, test, fmt, ...) expr1
165 #define __ASSERT_NO_MSG(test) { }
166 #endif
167 #else
168 #define __ASSERT(test, fmt, ...) { }
169 #define __ASSERT_EVAL(expr1, expr2, test, fmt, ...) expr1
170 #define __ASSERT_NO_MSG(test) { }
171 #endif
172 
173 #endif /* ZEPHYR_INCLUDE_SYS___ASSERT_H_ */
174