1 /*
2  * Copyright (c) 2011-2014 Wind River Systems, Inc.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef ZEPHYR_INCLUDE_SYS___ASSERT_H_
8 #define ZEPHYR_INCLUDE_SYS___ASSERT_H_
9 
10 #include <stdbool.h>
11 #include <zephyr/toolchain.h>
12 
13 #ifdef CONFIG_ASSERT
14 #ifndef __ASSERT_ON
15 #define __ASSERT_ON CONFIG_ASSERT_LEVEL
16 #endif
17 #endif
18 
19 #ifdef CONFIG_FORCE_NO_ASSERT
20 #undef __ASSERT_ON
21 #define __ASSERT_ON 0
22 #endif
23 
24 #ifdef __cplusplus
25 extern "C" {
26 #endif
27 
28 /* Wrapper around printk to avoid including printk.h in assert.h */
29 void __printf_like(1, 2) assert_print(const char *fmt, ...);
30 
31 #ifdef __cplusplus
32 }
33 #endif
34 
35 #if defined(CONFIG_ASSERT_VERBOSE)
36 #define __ASSERT_PRINT(fmt, ...) assert_print(fmt, ##__VA_ARGS__)
37 #else /* CONFIG_ASSERT_VERBOSE */
38 #define __ASSERT_PRINT(fmt, ...)
39 #endif /* CONFIG_ASSERT_VERBOSE */
40 
41 #ifdef CONFIG_ASSERT_NO_MSG_INFO
42 #define __ASSERT_MSG_INFO(fmt, ...)
43 #else  /* CONFIG_ASSERT_NO_MSG_INFO */
44 #define __ASSERT_MSG_INFO(fmt, ...) __ASSERT_PRINT("\t" fmt "\n", ##__VA_ARGS__)
45 #endif /* CONFIG_ASSERT_NO_MSG_INFO */
46 
47 #if !defined(CONFIG_ASSERT_NO_COND_INFO) && !defined(CONFIG_ASSERT_NO_FILE_INFO)
48 #define __ASSERT_LOC(test)                              \
49 	__ASSERT_PRINT("ASSERTION FAIL [%s] @ %s:%d\n", \
50 		Z_STRINGIFY(test),                      \
51 		__FILE__, __LINE__)
52 #endif
53 
54 #if defined(CONFIG_ASSERT_NO_COND_INFO) && !defined(CONFIG_ASSERT_NO_FILE_INFO)
55 #define __ASSERT_LOC(test)                         \
56 	__ASSERT_PRINT("ASSERTION FAIL @ %s:%d\n", \
57 		__FILE__, __LINE__)
58 #endif
59 
60 #if !defined(CONFIG_ASSERT_NO_COND_INFO) && defined(CONFIG_ASSERT_NO_FILE_INFO)
61 #define __ASSERT_LOC(test)                      \
62 	__ASSERT_PRINT("ASSERTION FAIL [%s]\n", \
63 		Z_STRINGIFY(test))
64 #endif
65 
66 #if defined(CONFIG_ASSERT_NO_COND_INFO) && defined(CONFIG_ASSERT_NO_FILE_INFO)
67 #define __ASSERT_LOC(test)                 \
68 	__ASSERT_PRINT("ASSERTION FAIL\n")
69 #endif
70 
71 #ifdef __ASSERT_ON
72 #if (__ASSERT_ON < 0) || (__ASSERT_ON > 2)
73 #error "Invalid __ASSERT() level: must be between 0 and 2"
74 #endif
75 
76 #if __ASSERT_ON
77 
78 #ifdef __cplusplus
79 extern "C" {
80 #endif
81 
82 #ifdef CONFIG_ASSERT_NO_FILE_INFO
83 void assert_post_action(void);
84 #define __ASSERT_POST_ACTION() assert_post_action()
85 #else  /* CONFIG_ASSERT_NO_FILE_INFO */
86 void assert_post_action(const char *file, unsigned int line);
87 #define __ASSERT_POST_ACTION() assert_post_action(__FILE__, __LINE__)
88 #endif /* CONFIG_ASSERT_NO_FILE_INFO */
89 
90 /*
91  * When the assert test mode is enabled, the default kernel fatal error handler
92  * and the custom assert hook function may return in order to allow the test to
93  * proceed.
94  */
95 #ifdef CONFIG_ASSERT_TEST
96 #define __ASSERT_UNREACHABLE
97 #else
98 #define __ASSERT_UNREACHABLE CODE_UNREACHABLE
99 #endif
100 
101 #ifdef __cplusplus
102 }
103 #endif
104 
105 #define __ASSERT_NO_MSG(test)                                             \
106 	do {                                                              \
107 		if (!(test)) {                                            \
108 			__ASSERT_LOC(test);                               \
109 			__ASSERT_POST_ACTION();                           \
110 			__ASSERT_UNREACHABLE;                             \
111 		}                                                         \
112 	} while (false)
113 
114 #define __ASSERT(test, fmt, ...)                                          \
115 	do {                                                              \
116 		if (!(test)) {                                            \
117 			__ASSERT_LOC(test);                               \
118 			__ASSERT_MSG_INFO(fmt, ##__VA_ARGS__);            \
119 			__ASSERT_POST_ACTION();                           \
120 			__ASSERT_UNREACHABLE;                             \
121 		}                                                         \
122 	} while (false)
123 
124 #define __ASSERT_EVAL(expr1, expr2, test, fmt, ...)                \
125 	do {                                                       \
126 		expr2;                                             \
127 		__ASSERT(test, fmt, ##__VA_ARGS__);                \
128 	} while (false)
129 
130 #if (__ASSERT_ON == 1)
131 #warning "__ASSERT() statements are ENABLED"
132 #endif
133 #else
134 #define __ASSERT(test, fmt, ...) { }
135 #define __ASSERT_EVAL(expr1, expr2, test, fmt, ...) expr1
136 #define __ASSERT_NO_MSG(test) { }
137 #define __ASSERT_POST_ACTION() { }
138 #endif
139 #else
140 #define __ASSERT(test, fmt, ...) { }
141 #define __ASSERT_EVAL(expr1, expr2, test, fmt, ...) expr1
142 #define __ASSERT_NO_MSG(test) { }
143 #define __ASSERT_POST_ACTION() { }
144 #endif
145 
146 #endif /* ZEPHYR_INCLUDE_SYS___ASSERT_H_ */
147