1 /*
2  * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #pragma once
7 
8 #include "esp_err.h"
9 #include "esp_log.h"
10 
11 #ifdef __cplusplus
12 extern "C" {
13 #endif
14 
15 /**
16  * Macro which can be used to check the error code. If the code is not ESP_OK, it prints the message and returns.
17  */
18 #if defined(CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT)
19 #define ESP_RETURN_ON_ERROR(x, log_tag, format, ...) do {                                       \
20         (void)log_tag;                                                                          \
21         esp_err_t err_rc_ = (x);                                                                \
22         if (unlikely(err_rc_ != ESP_OK)) {                                                      \
23             return err_rc_;                                                                     \
24         }                                                                                       \
25     } while(0)
26 
27 /**
28  * A version of ESP_RETURN_ON_ERROR() macro that can be called from ISR.
29  */
30 #define ESP_RETURN_ON_ERROR_ISR(x, log_tag, format, ...) do {                                   \
31         (void)log_tag;                                                                          \
32         esp_err_t err_rc_ = (x);                                                                \
33         if (unlikely(err_rc_ != ESP_OK)) {                                                      \
34             return err_rc_;                                                                     \
35         }                                                                                       \
36     } while(0)
37 
38 /**
39  * Macro which can be used to check the error code. If the code is not ESP_OK, it prints the message,
40  * sets the local variable 'ret' to the code, and then exits by jumping to 'goto_tag'.
41  */
42 #define ESP_GOTO_ON_ERROR(x, goto_tag, log_tag, format, ...) do {                               \
43         (void)log_tag;                                                                          \
44         esp_err_t err_rc_ = (x);                                                                \
45         if (unlikely(err_rc_ != ESP_OK)) {                                                      \
46             ret = err_rc_;                                                                      \
47             goto goto_tag;                                                                      \
48         }                                                                                       \
49     } while(0)
50 
51 /**
52  * A version of ESP_GOTO_ON_ERROR() macro that can be called from ISR.
53  */
54 #define ESP_GOTO_ON_ERROR_ISR(x, goto_tag, log_tag, format, ...) do {                           \
55         (void)log_tag;                                                                          \
56         esp_err_t err_rc_ = (x);                                                                \
57         if (unlikely(err_rc_ != ESP_OK)) {                                                      \
58             ret = err_rc_;                                                                      \
59             goto goto_tag;                                                                      \
60         }                                                                                       \
61     } while(0)
62 
63 /**
64  * Macro which can be used to check the condition. If the condition is not 'true', it prints the message
65  * and returns with the supplied 'err_code'.
66  */
67 #define ESP_RETURN_ON_FALSE(a, err_code, log_tag, format, ...) do {                             \
68         (void)log_tag;                                                                          \
69         if (unlikely(!(a))) {                                                                   \
70             return err_code;                                                                    \
71         }                                                                                       \
72     } while(0)
73 
74 /**
75  * A version of ESP_RETURN_ON_FALSE() macro that can be called from ISR.
76  */
77 #define ESP_RETURN_ON_FALSE_ISR(a, err_code, log_tag, format, ...) do {                         \
78         (void)log_tag;                                                                          \
79         if (unlikely(!(a))) {                                                                   \
80             return err_code;                                                                    \
81         }                                                                                       \
82     } while(0)
83 
84 /**
85  * Macro which can be used to check the condition. If the condition is not 'true', it prints the message,
86  * sets the local variable 'ret' to the supplied 'err_code', and then exits by jumping to 'goto_tag'.
87  */
88 #define ESP_GOTO_ON_FALSE(a, err_code, goto_tag, log_tag, format, ...) do {                     \
89         (void)log_tag;                                                                          \
90         if (unlikely(!(a))) {                                                                   \
91             ret = err_code;                                                                     \
92             goto goto_tag;                                                                      \
93         }                                                                                       \
94     } while (0)
95 
96 /**
97  * A version of ESP_GOTO_ON_FALSE() macro that can be called from ISR.
98  */
99 #define ESP_GOTO_ON_FALSE_ISR(a, err_code, goto_tag, log_tag, format, ...) do {                 \
100         (void)log_tag;                                                                          \
101         if (unlikely(!(a))) {                                                                   \
102             ret = err_code;                                                                     \
103             goto goto_tag;                                                                      \
104         }                                                                                       \
105     } while (0)
106 
107 #else // !CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT
108 
109 /**
110  * In the future, we want to switch to C++20. We also want to become compatible with clang.
111  * Hence, we provide two versions of the following macros. The first one is using the GNU extension \#\#__VA_ARGS__.
112  * The second one is using the C++20 feature __VA_OPT__(,). This allows users to compile their code with
113  * standard C++20 enabled instead of the GNU extension. Below C++20, we haven't found any good alternative to
114  * using \#\#__VA_ARGS__.
115  */
116 #if defined(__cplusplus) && (__cplusplus >  201703L)
117 
118 /**
119  * Macro which can be used to check the error code. If the code is not ESP_OK, it prints the message and returns.
120  */
121 #define ESP_RETURN_ON_ERROR(x, log_tag, format, ...) do {                                                  \
122         esp_err_t err_rc_ = (x);                                                                           \
123         if (unlikely(err_rc_ != ESP_OK)) {                                                                 \
124             ESP_LOGE(log_tag, "%s(%d): " format, __FUNCTION__, __LINE__ __VA_OPT__(,) __VA_ARGS__);        \
125             return err_rc_;                                                                                \
126         }                                                                                                  \
127     } while(0)
128 
129 /**
130  * A version of ESP_RETURN_ON_ERROR() macro that can be called from ISR.
131  */
132 #define ESP_RETURN_ON_ERROR_ISR(x, log_tag, format, ...) do {                                              \
133         esp_err_t err_rc_ = (x);                                                                           \
134         if (unlikely(err_rc_ != ESP_OK)) {                                                                 \
135             ESP_EARLY_LOGE(log_tag, "%s(%d): " format, __FUNCTION__, __LINE__ __VA_OPT__(,) __VA_ARGS__);  \
136             return err_rc_;                                                                                \
137         }                                                                                                  \
138     } while(0)
139 
140 /**
141  * Macro which can be used to check the error code. If the code is not ESP_OK, it prints the message,
142  * sets the local variable 'ret' to the code, and then exits by jumping to 'goto_tag'.
143  */
144 #define ESP_GOTO_ON_ERROR(x, goto_tag, log_tag, format, ...) do {                                          \
145         esp_err_t err_rc_ = (x);                                                                           \
146         if (unlikely(err_rc_ != ESP_OK)) {                                                                 \
147             ESP_LOGE(log_tag, "%s(%d): " format, __FUNCTION__, __LINE__ __VA_OPT__(,) __VA_ARGS__);        \
148             ret = err_rc_;                                                                                 \
149             goto goto_tag;                                                                                 \
150         }                                                                                                  \
151     } while(0)
152 
153 /**
154  * A version of ESP_GOTO_ON_ERROR() macro that can be called from ISR.
155  */
156 #define ESP_GOTO_ON_ERROR_ISR(x, goto_tag, log_tag, format, ...) do {                                      \
157         esp_err_t err_rc_ = (x);                                                                           \
158         if (unlikely(err_rc_ != ESP_OK)) {                                                                 \
159             ESP_EARLY_LOGE(log_tag, "%s(%d): " format, __FUNCTION__, __LINE__ __VA_OPT__(,) __VA_ARGS__);  \
160             ret = err_rc_;                                                                                 \
161             goto goto_tag;                                                                                 \
162         }                                                                                                  \
163     } while(0)
164 
165 /**
166  * Macro which can be used to check the condition. If the condition is not 'true', it prints the message
167  * and returns with the supplied 'err_code'.
168  */
169 #define ESP_RETURN_ON_FALSE(a, err_code, log_tag, format, ...) do {                                        \
170         if (unlikely(!(a))) {                                                                              \
171             ESP_LOGE(log_tag, "%s(%d): " format, __FUNCTION__, __LINE__ __VA_OPT__(,) __VA_ARGS__);        \
172             return err_code;                                                                               \
173         }                                                                                                  \
174     } while(0)
175 
176 /**
177  * A version of ESP_RETURN_ON_FALSE() macro that can be called from ISR.
178  */
179 #define ESP_RETURN_ON_FALSE_ISR(a, err_code, log_tag, format, ...) do {                                    \
180         if (unlikely(!(a))) {                                                                              \
181             ESP_EARLY_LOGE(log_tag, "%s(%d): " format, __FUNCTION__, __LINE__ __VA_OPT__(,) __VA_ARGS__);  \
182             return err_code;                                                                               \
183         }                                                                                                  \
184     } while(0)
185 
186 /**
187  * Macro which can be used to check the condition. If the condition is not 'true', it prints the message,
188  * sets the local variable 'ret' to the supplied 'err_code', and then exits by jumping to 'goto_tag'.
189  */
190 #define ESP_GOTO_ON_FALSE(a, err_code, goto_tag, log_tag, format, ...) do {                                \
191         if (unlikely(!(a))) {                                                                              \
192             ESP_LOGE(log_tag, "%s(%d): " format, __FUNCTION__, __LINE__ __VA_OPT__(,) __VA_ARGS__);        \
193             ret = err_code;                                                                                \
194             goto goto_tag;                                                                                 \
195         }                                                                                                  \
196     } while (0)
197 
198 /**
199  * A version of ESP_GOTO_ON_FALSE() macro that can be called from ISR.
200  */
201 #define ESP_GOTO_ON_FALSE_ISR(a, err_code, goto_tag, log_tag, format, ...) do {                            \
202         if (unlikely(!(a))) {                                                                              \
203             ESP_EARLY_LOGE(log_tag, "%s(%d): " format, __FUNCTION__, __LINE__ __VA_OPT__(,) __VA_ARGS__);  \
204             ret = err_code;                                                                                \
205             goto goto_tag;                                                                                 \
206         }                                                                                                  \
207     } while (0)
208 
209 #else // !(defined(__cplusplus) && (__cplusplus >  201703L))
210 
211 /**
212  * Macro which can be used to check the error code. If the code is not ESP_OK, it prints the message and returns.
213  */
214 #define ESP_RETURN_ON_ERROR(x, log_tag, format, ...) do {                                       \
215         esp_err_t err_rc_ = (x);                                                                \
216         if (unlikely(err_rc_ != ESP_OK)) {                                                      \
217             ESP_LOGE(log_tag, "%s(%d): " format, __FUNCTION__, __LINE__, ##__VA_ARGS__);        \
218             return err_rc_;                                                                     \
219         }                                                                                       \
220     } while(0)
221 
222 /**
223  * A version of ESP_RETURN_ON_ERROR() macro that can be called from ISR.
224  */
225 #define ESP_RETURN_ON_ERROR_ISR(x, log_tag, format, ...) do {                                   \
226         esp_err_t err_rc_ = (x);                                                                \
227         if (unlikely(err_rc_ != ESP_OK)) {                                                      \
228             ESP_EARLY_LOGE(log_tag, "%s(%d): " format, __FUNCTION__, __LINE__, ##__VA_ARGS__);  \
229             return err_rc_;                                                                     \
230         }                                                                                       \
231     } while(0)
232 
233 /**
234  * Macro which can be used to check the error code. If the code is not ESP_OK, it prints the message,
235  * sets the local variable 'ret' to the code, and then exits by jumping to 'goto_tag'.
236  */
237 #define ESP_GOTO_ON_ERROR(x, goto_tag, log_tag, format, ...) do {                               \
238         esp_err_t err_rc_ = (x);                                                                \
239         if (unlikely(err_rc_ != ESP_OK)) {                                                      \
240             ESP_LOGE(log_tag, "%s(%d): " format, __FUNCTION__, __LINE__, ##__VA_ARGS__);        \
241             ret = err_rc_;                                                                      \
242             goto goto_tag;                                                                      \
243         }                                                                                       \
244     } while(0)
245 
246 /**
247  * A version of ESP_GOTO_ON_ERROR() macro that can be called from ISR.
248  */
249 #define ESP_GOTO_ON_ERROR_ISR(x, goto_tag, log_tag, format, ...) do {                           \
250         esp_err_t err_rc_ = (x);                                                                \
251         if (unlikely(err_rc_ != ESP_OK)) {                                                      \
252             ESP_EARLY_LOGE(log_tag, "%s(%d): " format, __FUNCTION__, __LINE__, ##__VA_ARGS__);  \
253             ret = err_rc_;                                                                      \
254             goto goto_tag;                                                                      \
255         }                                                                                       \
256     } while(0)
257 
258 /**
259  * Macro which can be used to check the condition. If the condition is not 'true', it prints the message
260  * and returns with the supplied 'err_code'.
261  */
262 #define ESP_RETURN_ON_FALSE(a, err_code, log_tag, format, ...) do {                             \
263         if (unlikely(!(a))) {                                                                   \
264             ESP_LOGE(log_tag, "%s(%d): " format, __FUNCTION__, __LINE__, ##__VA_ARGS__);        \
265             return err_code;                                                                    \
266         }                                                                                       \
267     } while(0)
268 
269 /**
270  * A version of ESP_RETURN_ON_FALSE() macro that can be called from ISR.
271  */
272 #define ESP_RETURN_ON_FALSE_ISR(a, err_code, log_tag, format, ...) do {                         \
273         if (unlikely(!(a))) {                                                                   \
274             ESP_EARLY_LOGE(log_tag, "%s(%d): " format, __FUNCTION__, __LINE__, ##__VA_ARGS__);  \
275             return err_code;                                                                    \
276         }                                                                                       \
277     } while(0)
278 
279 /**
280  * Macro which can be used to check the condition. If the condition is not 'true', it prints the message,
281  * sets the local variable 'ret' to the supplied 'err_code', and then exits by jumping to 'goto_tag'.
282  */
283 #define ESP_GOTO_ON_FALSE(a, err_code, goto_tag, log_tag, format, ...) do {                     \
284         if (unlikely(!(a))) {                                                                   \
285             ESP_LOGE(log_tag, "%s(%d): " format, __FUNCTION__, __LINE__, ##__VA_ARGS__);        \
286             ret = err_code;                                                                     \
287             goto goto_tag;                                                                      \
288         }                                                                                       \
289     } while (0)
290 
291 /**
292  * A version of ESP_GOTO_ON_FALSE() macro that can be called from ISR.
293  */
294 #define ESP_GOTO_ON_FALSE_ISR(a, err_code, goto_tag, log_tag, format, ...) do {                 \
295         if (unlikely(!(a))) {                                                                   \
296             ESP_EARLY_LOGE(log_tag, "%s(%d): " format, __FUNCTION__, __LINE__, ##__VA_ARGS__);  \
297             ret = err_code;                                                                     \
298             goto goto_tag;                                                                      \
299         }                                                                                       \
300     } while (0)
301 
302 #endif // !(defined(__cplusplus) && (__cplusplus >  201703L))
303 
304 #endif // !CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT
305 
306 
307 #ifdef __cplusplus
308 }
309 #endif
310