debug.h 23 KB

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