1 /* 2 * Copyright (C) 2019-2020 Alibaba Group Holding Limited 3 */ 4 5 #ifndef OSAL_DEBUG_H 6 #define OSAL_DEBUG_H 7 8 #include <stdio.h> 9 #include <string.h> 10 #include <errno.h> 11 #include <ulog/ulog.h> 12 13 #ifdef __cplusplus 14 extern "C" { 15 #endif 16 17 #define SHORT_FILE __FUNCTION__ 18 19 #ifdef CONFIG_DEBUG 20 #define debug_print_assert(A, B, C, D, E, F) \ 21 do { \ 22 printf("!!!assert: %s: %d, %s\r\n", D, E, F); \ 23 while (1) \ 24 ; \ 25 } while (0) 26 #else 27 #define debug_print_assert(A, B, C, D, E, F) 28 #endif 29 30 #if (!defined(unlikely)) 31 #define unlikely(EXPRESSSION) !!(EXPRESSSION) 32 #endif 33 34 #ifdef CONFIG_DEBUG 35 36 #define aos_assert(X) \ 37 do { \ 38 if (unlikely(!(X))) { \ 39 debug_print_assert(0, #X, NULL, SHORT_FILE, __LINE__, __PRETTY_FUNCTION__); \ 40 } \ 41 } while (0) 42 43 #define except_process(err) aos_except_process(errno, SHORT_FILE, __LINE__, \ 44 __PRETTY_FUNCTION__, __builtin_return_address(0)) 45 46 #else 47 48 #define aos_assert(X) 49 #define except_process(err) aos_except_process(errno, NULL, 0, NULL, \ 50 __builtin_return_address(0)) 51 #endif 52 53 #ifndef CHECK_PARAM 54 #define CHECK_PARAM(x, ret) \ 55 do { \ 56 if (!(x)) { \ 57 return ret; \ 58 }\ 59 } while (0) 60 #endif 61 62 #ifndef CHECK_RET_WITH_GOTO 63 #define CHECK_RET_WITH_GOTO(x, label) \ 64 do { \ 65 if (!(x)) { \ 66 printf("%s, %d fail.\n", __FUNCTION__, __LINE__); \ 67 goto label; \ 68 }\ 69 } while (0) 70 #endif 71 72 #ifndef CHECK_RET_WITH_RET 73 #define CHECK_RET_WITH_RET(x, ret) \ 74 do { \ 75 if (!(x)) { \ 76 printf("%s, %d fail.\n", __FUNCTION__, __LINE__); \ 77 return ret; \ 78 }\ 79 } while (0) 80 #endif 81 82 #ifndef CHECK_RET_TAG_WITH_GOTO 83 #define CHECK_RET_TAG_WITH_GOTO(x, label) \ 84 do { \ 85 if (!(x)) { \ 86 LOGE(TAG, "%s, %d fail", __FUNCTION__, __LINE__); \ 87 goto label; \ 88 }\ 89 } while (0) 90 #endif 91 92 #ifndef CHECK_RET_TAG_WITH_RET 93 #define CHECK_RET_TAG_WITH_RET(x, ret) \ 94 do { \ 95 if (!(x)) { \ 96 LOGE(TAG, "%s, %d fail", __FUNCTION__, __LINE__); \ 97 return ret; \ 98 }\ 99 } while (0) 100 #endif 101 102 /* 103 * Check that an expression is true (non-zero). 104 * If expression evalulates to false, this prints debugging information (actual expression string, file, line number, 105 * function name, etc.) using the default debugging output method. 106 * 107 * @param[in] X expression to be evaluated. 108 */ 109 110 #if (!defined(aos_check)) 111 #define aos_check(X, errno) \ 112 do { \ 113 if (unlikely(!(X))) \ 114 except_process(errno); \ 115 } while (0) 116 #endif 117 118 #if (!defined(aos_check_param)) 119 #define aos_check_param(X) aos_check(X, EINVAL) 120 #endif 121 122 #if (!defined(aos_check_mem)) 123 #define aos_check_mem(X) aos_check(X, ENOMEM) 124 #endif 125 126 #if (!defined(aos_check_return_val)) 127 #define aos_check_return_val(X, ret) \ 128 do { \ 129 if (unlikely(!(X))) { \ 130 except_process(errno); \ 131 return ret; \ 132 } \ 133 } while (0) 134 #endif 135 136 #if (!defined(aos_check_return_einval)) 137 #define aos_check_return_einval(X) aos_check_return_val(X, -EINVAL) 138 #endif 139 140 #if (!defined(aos_check_return_null)) 141 #define aos_check_return_null(X) aos_check_return_val(X, NULL) 142 #endif 143 144 #if (!defined(aos_check_return_enomem)) 145 #define aos_check_return_enomem(X) aos_check_return_val(X, -ENOMEM) 146 #endif 147 148 #if (!defined(aos_check_return)) 149 #define aos_check_return(X) \ 150 do { \ 151 if (unlikely(!(X))) { \ 152 except_process(errno); \ 153 return; \ 154 } \ 155 } while (0) 156 #endif 157 158 ////////////////////////////////////////////////////////////////////// 159 160 #if (!defined(check)) 161 #define check(X) \ 162 do { \ 163 if (unlikely(!(X))) \ 164 except_process(0); \ 165 } while (0) 166 #endif 167 /* 168 * Check that an expression is true (non-zero) with an explanation. 169 * If expression evalulates to false, this prints debugging information (actual expression string, file, line number, 170 * function name, etc.) using the default debugging output method. 171 * 172 * @param[in] X expression to be evaluated. 173 * @param[in] STR If the expression evaluate to false, custom string to print. 174 */ 175 #if (!defined(check_string)) 176 #define check_string(X, STR) \ 177 do { \ 178 if (unlikely(!(X))) { \ 179 debug_print_assert(0, #X, STR, SHORT_FILE, __LINE__, __PRETTY_FUNCTION__); \ 180 AOS_ASSERTION_FAIL_ACTION(); \ 181 } \ 182 } while (1 == 0) 183 #endif 184 185 /* 186 * Requires that an expression evaluate to true. 187 * If expression evalulates to false, this prints debugging information (actual expression string, file, line number, 188 * function name, etc.) using the default debugging output method then jumps to a label. 189 * 190 * @param[in] X expression to be evalulated. 191 * @param[in] LABEL if expression evaluate to false,jumps to the LABEL. 192 */ 193 #if (!defined(require)) 194 #define require(X, LABEL) \ 195 do { \ 196 if (unlikely(!(X))) { \ 197 debug_print_assert(0, #X, NULL, SHORT_FILE, __LINE__, __PRETTY_FUNCTION__); \ 198 goto LABEL; \ 199 } \ 200 } while (1 == 0) 201 #endif 202 203 /* 204 * Requires that an expression evaluate to true with an explanation. 205 * If expression evalulates to false, this prints debugging information (actual expression string, file, line number, 206 * function name, etc.) and a custom explanation string using the default debugging output method then jumps to a label. 207 * 208 * @param[in] X expression to be evalulated. 209 * @param[in] LABEL if expression evaluate to false,jumps to the LABEL. 210 * @param[in] STR if expression evaluate to false,custom explanation string to print. 211 */ 212 #if (!defined(require_string)) 213 #define require_string(X, LABEL, STR) \ 214 do { \ 215 if (unlikely(!(X))) { \ 216 debug_print_assert(0, #X, STR, SHORT_FILE, __LINE__, __PRETTY_FUNCTION__); \ 217 goto LABEL; \ 218 } \ 219 } while (1 == 0) 220 #endif 221 222 /* 223 * Requires that an expression evaluate to true. 224 * If expression evalulates to false, this jumps to a label. No debugging information is printed. 225 * 226 * @param[in] X expression to be evalulated 227 * @param[in] LABEL if expression evaluate to false,jumps to the LABEL. 228 */ 229 #if (!defined(require_quiet)) 230 #define require_quiet(X, LABEL) \ 231 do { \ 232 if (unlikely(!(X))) { \ 233 goto LABEL; \ 234 } \ 235 } while (1 == 0) 236 #endif 237 238 /* 239 * Require that an error code is noErr (0). 240 * If the error code is non-0, this prints debugging information (actual expression string, file, line number, 241 * function name, etc.) using the default debugging output method then jumps to a label. 242 * 243 * @param[in] ERR error to be evaluated 244 * @param[in] LABEL If the error code is non-0,jumps to the LABEL. 245 */ 246 #if (!defined(require_noerr)) 247 #define require_noerr(ERR, LABEL) \ 248 do { \ 249 int localErr; \ 250 \ 251 localErr = (int)(ERR); \ 252 if (unlikely(localErr != 0)) { \ 253 debug_print_assert(localErr, NULL, NULL, SHORT_FILE, __LINE__, __PRETTY_FUNCTION__); \ 254 goto LABEL; \ 255 } \ 256 \ 257 } while (1 == 0) 258 #endif 259 260 /* 261 * Require that an error code is noErr (0) with an explanation. 262 * If the error code is non-0, this prints debugging information (actual expression string, file, line number, 263 * function name, etc.), and a custom explanation string using the default debugging output method using the 264 * default debugging output method then jumps to a label. 265 * 266 * @param[in] ERR error to be evaluated 267 * @param[in] LABEL If the error code is non-0, jumps to the LABEL. 268 * @param[in] STR If the error code is non-0, custom explanation string to print 269 */ 270 #if (!defined(require_noerr_string)) 271 #define require_noerr_string(ERR, LABEL, STR) \ 272 do { \ 273 int localErr; \ 274 \ 275 localErr = (int)(ERR); \ 276 if (unlikely(localErr != 0)) { \ 277 debug_print_assert(localErr, NULL, STR, SHORT_FILE, __LINE__, __PRETTY_FUNCTION__); \ 278 goto LABEL; \ 279 } \ 280 } while (1 == 0) 281 #endif 282 283 /* 284 * Require that an error code is noErr (0) with an explanation and action to execute otherwise. 285 * If the error code is non-0, this prints debugging information (actual expression string, file, line number, 286 * function name, etc.), and a custom explanation string using the default debugging output method using the 287 * default debugging output method then executes an action and jumps to a label. 288 * 289 * @param[in] ERR error to be evaluated. 290 * @param[in] LABEL If the error code is non-0, jumps to the LABEL. 291 * @param[in] ACTION If the error code is non-0, custom code to executes. 292 * @param[in] STR If the error code is non-0, custom explanation string to print. 293 */ 294 #if (!defined(require_noerr_action_string)) 295 #define require_noerr_action_string(ERR, LABEL, ACTION, STR) \ 296 do { \ 297 int localErr; \ 298 \ 299 localErr = (int)(ERR); \ 300 if (unlikely(localErr != 0)) { \ 301 debug_print_assert(localErr, NULL, STR, SHORT_FILE, __LINE__, __PRETTY_FUNCTION__); \ 302 { \ 303 ACTION; \ 304 } \ 305 goto LABEL; \ 306 } \ 307 } while (1 == 0) 308 #endif 309 310 /* 311 * Require that an error code is noErr (0). 312 * If the error code is non-0, this jumps to a label. No debugging information is printed. 313 * 314 * @param[in] ERR error to be evaluated. 315 * @param[in] LABEL If the error code is non-0, jumps to the LABEL. 316 */ 317 #if (!defined(require_noerr_quiet)) 318 #define require_noerr_quiet(ERR, LABEL) \ 319 do { \ 320 if (unlikely((ERR) != 0)) { \ 321 goto LABEL; \ 322 } \ 323 } while (1 == 0) 324 #endif 325 326 /* 327 * Require that an error code is noErr (0) with an action to execute otherwise. 328 * If the error code is non-0, this prints debugging information (actual expression string, file, line number, 329 * function name, etc.) using the default debugging output method then executes an action and jumps to a label. 330 * 331 * @param[in] ERR error to be evaluated. 332 * @param[in] LABEL If the error code is non-0, jumps to the LABEL. 333 * @param[in] ACTION If the error code is non-0, custom code to executes. 334 */ 335 #if (!defined(require_noerr_action)) 336 #define require_noerr_action(ERR, LABEL, ACTION) \ 337 do { \ 338 int localErr; \ 339 \ 340 localErr = (int)(ERR); \ 341 if (unlikely(localErr != 0)) { \ 342 debug_print_assert(localErr, NULL, NULL, SHORT_FILE, __LINE__, __PRETTY_FUNCTION__); \ 343 { \ 344 ACTION; \ 345 } \ 346 goto LABEL; \ 347 } \ 348 } while (1 == 0) 349 #endif 350 351 /* 352 * Require that an error code is noErr (0) with an action to execute otherwise. 353 * If the error code is non-0, this executes an action and jumps to a label. No debugging information is printed. 354 * 355 * @param[in] ERR error to be evaluated. 356 * @param[in] LABEL If the error code is non-0, jumps to the LABEL. 357 * @param[in] ACTION If the error code is non-0, custom code to executes. 358 */ 359 #if (!defined(require_noerr_action_quiet)) 360 #define require_noerr_action_quiet(ERR, LABEL, ACTION) \ 361 do { \ 362 if (unlikely((ERR) != 0)) { \ 363 { \ 364 ACTION; \ 365 } \ 366 goto LABEL; \ 367 } \ 368 } while (1 == 0) 369 #endif 370 371 /* 372 * Requires that an expression evaluate to true with an action to execute otherwise. 373 * If expression evalulates to false, this prints debugging information (actual expression string, file, line number, 374 * function name, etc.) using the default debugging output method then executes an action and jumps to a label. 375 * 376 * @param[in] X expression to be evaluated. 377 * @param[in] LABEL If the expression evaluate to false, jumps to the LABEL. 378 * @param[in] ACTION If the expression evaluate to false, custom code to executes. 379 */ 380 #if (!defined(require_action)) 381 #define require_action(X, LABEL, ACTION) \ 382 do { \ 383 if (unlikely(!(X))) { \ 384 debug_print_assert(0, #X, NULL, SHORT_FILE, __LINE__, __PRETTY_FUNCTION__); \ 385 { \ 386 ACTION; \ 387 } \ 388 goto LABEL; \ 389 } \ 390 } while (1 == 0) 391 #endif 392 393 /* 394 * Requires that an expression evaluate to true with an explanation and action to execute otherwise. 395 * If expression evalulates to false, this prints debugging information (actual expression string, file, line number, 396 * function name, etc.) and a custom explanation string using the default debugging output method then executes an 397 * action and jumps to a label. 398 * 399 * @param[in] X expression to be evaluated. 400 * @param[in] LABEL If the expression evaluate to false, jumps to the LABEL. 401 * @param[in] ACTION If the expression evaluate to false, custom code to executes. 402 * @param[in] STR If the expression evaluate to false, custom string to print. 403 */ 404 #if (!defined(require_action_string)) 405 #define require_action_string(X, LABEL, ACTION, STR) \ 406 do { \ 407 if (unlikely(!(X))) { \ 408 debug_print_assert(0, #X, STR, SHORT_FILE, __LINE__, __PRETTY_FUNCTION__); \ 409 { \ 410 ACTION; \ 411 } \ 412 goto LABEL; \ 413 } \ 414 } while (1 == 0) 415 #endif 416 417 /* 418 * Requires that an expression evaluate to true with an action to execute otherwise. 419 * If expression evalulates to false, this executes an action and jumps to a label. 420 * No debugging information is printed. 421 * 422 * @param[in] X expression to be evaluated. 423 * @param[in] LABEL If the expression evaluate to false, jumps to the LABEL. 424 * @param[in] ACTION If the expression evaluate to false, custom code to executes. 425 */ 426 #if (!defined(require_action_quiet)) 427 #define require_action_quiet(X, LABEL, ACTION) \ 428 do { \ 429 if (unlikely(!(X))) { \ 430 { \ 431 ACTION; \ 432 } \ 433 goto LABEL; \ 434 } \ 435 \ 436 } while (1 == 0) 437 #endif 438 439 #ifdef __cplusplus 440 } 441 #endif 442 443 void aos_except_process(int errno, const char *file, int line, const char *func_name, void *caller); 444 445 #endif /* OSAL_DEBUG_H */ 446