kservice.c 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615
  1. /*
  2. * Copyright (c) 2006-2018, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2006-03-16 Bernard the first version
  9. * 2006-05-25 Bernard rewrite vsprintf
  10. * 2006-08-10 Bernard add rt_show_version
  11. * 2010-03-17 Bernard remove rt_strlcpy function
  12. * fix gcc compiling issue.
  13. * 2010-04-15 Bernard remove weak definition on ICCM16C compiler
  14. * 2012-07-18 Arda add the alignment display for signed integer
  15. * 2012-11-23 Bernard fix IAR compiler error.
  16. * 2012-12-22 Bernard fix rt_kprintf issue, which found by Grissiom.
  17. * 2013-06-24 Bernard remove rt_kprintf if RT_USING_CONSOLE is not defined.
  18. * 2013-09-24 aozima make sure the device is in STREAM mode when used by rt_kprintf.
  19. * 2015-07-06 Bernard Add rt_assert_handler routine.
  20. */
  21. #include <rtthread.h>
  22. #include <rthw.h>
  23. #ifdef RT_USING_MODULE
  24. #include <dlmodule.h>
  25. #endif
  26. #ifdef RT_USING_LWP
  27. #include <lwp.h>
  28. #include <lwp_user_mm.h>
  29. #include <console.h>
  30. #endif
  31. /* use precision */
  32. #define RT_PRINTF_PRECISION
  33. /**
  34. * @addtogroup KernelService
  35. */
  36. /**@{*/
  37. /* global errno in RT-Thread */
  38. static volatile int __rt_errno;
  39. #if defined(RT_USING_DEVICE) && defined(RT_USING_CONSOLE)
  40. static rt_device_t _console_device = RT_NULL;
  41. #endif
  42. static const char* rt_errno_strs[] =
  43. {
  44. "OK",
  45. "ERROR",
  46. "ETIMOUT",
  47. "ERSFULL",
  48. "ERSEPTY",
  49. "ENOMEM",
  50. "ENOSYS",
  51. "EBUSY",
  52. "EIO",
  53. "EINTRPT",
  54. "EINVAL",
  55. "EUNKNOW"
  56. };
  57. /**
  58. * This function return a pointer to a string that contains the
  59. * message of error.
  60. *
  61. * @param error the errorno code
  62. * @return a point to error message string
  63. */
  64. const char *rt_strerror(rt_err_t error)
  65. {
  66. if (error < 0)
  67. error = -error;
  68. return (error > RT_EINVAL + 1) ?
  69. rt_errno_strs[RT_EINVAL + 1] :
  70. rt_errno_strs[error];
  71. }
  72. RTM_EXPORT(rt_strerror);
  73. /*
  74. * This function will get errno
  75. *
  76. * @return errno
  77. */
  78. rt_err_t rt_get_errno(void)
  79. {
  80. rt_thread_t tid = RT_NULL;
  81. if (rt_interrupt_get_nest() != 0)
  82. {
  83. /* it's in interrupt context */
  84. return __rt_errno;
  85. }
  86. tid = rt_thread_self();
  87. if (tid == RT_NULL)
  88. {
  89. return __rt_errno;
  90. }
  91. return tid->error;
  92. }
  93. RTM_EXPORT(rt_get_errno);
  94. /*
  95. * This function will set errno
  96. *
  97. * @param error the errno shall be set
  98. */
  99. void rt_set_errno(rt_err_t error)
  100. {
  101. rt_thread_t tid = RT_NULL;
  102. if (rt_interrupt_get_nest() != 0)
  103. {
  104. /* it's in interrupt context */
  105. __rt_errno = error;
  106. return;
  107. }
  108. tid = rt_thread_self();
  109. if (tid == RT_NULL)
  110. {
  111. __rt_errno = error;
  112. return;
  113. }
  114. tid->error = error;
  115. }
  116. RTM_EXPORT(rt_set_errno);
  117. /**
  118. * This function returns errno.
  119. *
  120. * @return the errno in the system
  121. */
  122. int *_rt_errno(void)
  123. {
  124. rt_thread_t tid = RT_NULL;
  125. if (rt_interrupt_get_nest() != 0)
  126. {
  127. return (int *)&__rt_errno;
  128. }
  129. tid = rt_thread_self();
  130. if (tid != RT_NULL)
  131. {
  132. return (int *) & (tid->error);
  133. }
  134. return (int *)&__rt_errno;
  135. }
  136. RTM_EXPORT(_rt_errno);
  137. /**
  138. * This function will set the content of memory to specified value
  139. *
  140. * @param s the address of source memory
  141. * @param c the value shall be set in content
  142. * @param count the copied length
  143. *
  144. * @return the address of source memory
  145. */
  146. void *rt_memset(void *s, int c, rt_ubase_t count)
  147. {
  148. #ifdef RT_USING_TINY_SIZE
  149. char *xs = (char *)s;
  150. while (count--)
  151. *xs++ = c;
  152. return s;
  153. #else
  154. #define LBLOCKSIZE (sizeof(long))
  155. #define UNALIGNED(X) ((long)X & (LBLOCKSIZE - 1))
  156. #define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE)
  157. unsigned int i = 0;
  158. char *m = (char *)s;
  159. unsigned long buffer = 0;
  160. unsigned long *aligned_addr = RT_NULL;
  161. unsigned int d = c & 0xff; /* To avoid sign extension, copy C to an
  162. unsigned variable. */
  163. if (!TOO_SMALL(count) && !UNALIGNED(s))
  164. {
  165. /* If we get this far, we know that n is large and m is word-aligned. */
  166. aligned_addr = (unsigned long *)s;
  167. /* Store D into each char sized location in BUFFER so that
  168. * we can set large blocks quickly.
  169. */
  170. if (LBLOCKSIZE == 4)
  171. {
  172. buffer = (d << 8) | d;
  173. buffer |= (buffer << 16);
  174. }
  175. else
  176. {
  177. buffer = 0;
  178. for (i = 0; i < LBLOCKSIZE; i ++)
  179. {
  180. buffer = (buffer << 8) | d;
  181. }
  182. }
  183. while (count >= LBLOCKSIZE * 4)
  184. {
  185. *aligned_addr++ = buffer;
  186. *aligned_addr++ = buffer;
  187. *aligned_addr++ = buffer;
  188. *aligned_addr++ = buffer;
  189. count -= 4 * LBLOCKSIZE;
  190. }
  191. while (count >= LBLOCKSIZE)
  192. {
  193. *aligned_addr++ = buffer;
  194. count -= LBLOCKSIZE;
  195. }
  196. /* Pick up the remainder with a bytewise loop. */
  197. m = (char *)aligned_addr;
  198. }
  199. while (count--)
  200. {
  201. *m++ = (char)d;
  202. }
  203. return s;
  204. #undef LBLOCKSIZE
  205. #undef UNALIGNED
  206. #undef TOO_SMALL
  207. #endif
  208. }
  209. RTM_EXPORT(rt_memset);
  210. /**
  211. * This function will copy memory content from source address to destination
  212. * address.
  213. *
  214. * @param dst the address of destination memory
  215. * @param src the address of source memory
  216. * @param count the copied length
  217. *
  218. * @return the address of destination memory
  219. */
  220. void *rt_memcpy(void *dst, const void *src, rt_ubase_t count)
  221. {
  222. #ifdef RT_USING_TINY_SIZE
  223. char *tmp = (char *)dst, *s = (char *)src;
  224. rt_ubase_t len = 0;
  225. if (tmp <= s || tmp > (s + count))
  226. {
  227. while (count--)
  228. {
  229. *tmp ++ = *s ++;
  230. }
  231. }
  232. else
  233. {
  234. for (len = count; len > 0; len --)
  235. {
  236. tmp[len - 1] = s[len - 1];
  237. }
  238. }
  239. return dst;
  240. #else
  241. #define UNALIGNED(X, Y) \
  242. (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
  243. #define BIGBLOCKSIZE (sizeof (long) << 2)
  244. #define LITTLEBLOCKSIZE (sizeof (long))
  245. #define TOO_SMALL(LEN) ((LEN) < BIGBLOCKSIZE)
  246. char *dst_ptr = (char *)dst;
  247. char *src_ptr = (char *)src;
  248. long *aligned_dst = RT_NULL;
  249. long *aligned_src = RT_NULL;
  250. int len = count;
  251. /* If the size is small, or either SRC or DST is unaligned,
  252. then punt into the byte copy loop. This should be rare. */
  253. if (!TOO_SMALL(len) && !UNALIGNED(src_ptr, dst_ptr))
  254. {
  255. aligned_dst = (long *)dst_ptr;
  256. aligned_src = (long *)src_ptr;
  257. /* Copy 4X long words at a time if possible. */
  258. while (len >= BIGBLOCKSIZE)
  259. {
  260. *aligned_dst++ = *aligned_src++;
  261. *aligned_dst++ = *aligned_src++;
  262. *aligned_dst++ = *aligned_src++;
  263. *aligned_dst++ = *aligned_src++;
  264. len -= BIGBLOCKSIZE;
  265. }
  266. /* Copy one long word at a time if possible. */
  267. while (len >= LITTLEBLOCKSIZE)
  268. {
  269. *aligned_dst++ = *aligned_src++;
  270. len -= LITTLEBLOCKSIZE;
  271. }
  272. /* Pick up any residual with a byte copier. */
  273. dst_ptr = (char *)aligned_dst;
  274. src_ptr = (char *)aligned_src;
  275. }
  276. while (len--)
  277. {
  278. *dst_ptr++ = *src_ptr++;
  279. }
  280. return dst;
  281. #undef UNALIGNED
  282. #undef BIGBLOCKSIZE
  283. #undef LITTLEBLOCKSIZE
  284. #undef TOO_SMALL
  285. #endif
  286. }
  287. RTM_EXPORT(rt_memcpy);
  288. /**
  289. * This function will move memory content from source address to destination
  290. * address.
  291. *
  292. * @param dest the address of destination memory
  293. * @param src the address of source memory
  294. * @param n the copied length
  295. *
  296. * @return the address of destination memory
  297. */
  298. void *rt_memmove(void *dest, const void *src, rt_ubase_t n)
  299. {
  300. char *tmp = (char *)dest, *s = (char *)src;
  301. if (s < tmp && tmp < s + n)
  302. {
  303. tmp += n;
  304. s += n;
  305. while (n--)
  306. {
  307. *(--tmp) = *(--s);
  308. }
  309. }
  310. else
  311. {
  312. while (n--)
  313. {
  314. *tmp++ = *s++;
  315. }
  316. }
  317. return dest;
  318. }
  319. RTM_EXPORT(rt_memmove);
  320. /**
  321. * This function will compare two areas of memory
  322. *
  323. * @param cs one area of memory
  324. * @param ct another area of memory
  325. * @param count the size of the area
  326. *
  327. * @return the result
  328. */
  329. rt_int32_t rt_memcmp(const void *cs, const void *ct, rt_ubase_t count)
  330. {
  331. const unsigned char *su1 = RT_NULL, *su2 = RT_NULL;
  332. int res = 0;
  333. for (su1 = (const unsigned char *)cs, su2 = (const unsigned char *)ct; 0 < count; ++su1, ++su2, count--)
  334. {
  335. if ((res = *su1 - *su2) != 0)
  336. {
  337. break;
  338. }
  339. }
  340. return res;
  341. }
  342. RTM_EXPORT(rt_memcmp);
  343. /**
  344. * This function will return the first occurrence of a string.
  345. *
  346. * @param s1 the source string
  347. * @param s2 the find string
  348. *
  349. * @return the first occurrence of a s2 in s1, or RT_NULL if no found.
  350. */
  351. char *rt_strstr(const char *s1, const char *s2)
  352. {
  353. int l1 = 0, l2 = 0;
  354. l2 = rt_strlen(s2);
  355. if (!l2)
  356. {
  357. return (char *)s1;
  358. }
  359. l1 = rt_strlen(s1);
  360. while (l1 >= l2)
  361. {
  362. l1 --;
  363. if (!rt_memcmp(s1, s2, l2))
  364. {
  365. return (char *)s1;
  366. }
  367. s1 ++;
  368. }
  369. return RT_NULL;
  370. }
  371. RTM_EXPORT(rt_strstr);
  372. /**
  373. * This function will compare two strings while ignoring differences in case
  374. *
  375. * @param a the string to be compared
  376. * @param b the string to be compared
  377. *
  378. * @return the result
  379. */
  380. rt_int32_t rt_strcasecmp(const char *a, const char *b)
  381. {
  382. int ca = 0, cb = 0;
  383. do
  384. {
  385. ca = *a++ & 0xff;
  386. cb = *b++ & 0xff;
  387. if (ca >= 'A' && ca <= 'Z')
  388. ca += 'a' - 'A';
  389. if (cb >= 'A' && cb <= 'Z')
  390. cb += 'a' - 'A';
  391. }
  392. while (ca == cb && ca != '\0');
  393. return ca - cb;
  394. }
  395. RTM_EXPORT(rt_strcasecmp);
  396. /**
  397. * This function will copy string no more than n bytes.
  398. *
  399. * @param dst the string to copy
  400. * @param src the string to be copied
  401. * @param n the maximum copied length
  402. *
  403. * @return the result
  404. */
  405. char *rt_strncpy(char *dst, const char *src, rt_ubase_t n)
  406. {
  407. if (n != 0)
  408. {
  409. char *d = dst;
  410. const char *s = src;
  411. do
  412. {
  413. if ((*d++ = *s++) == 0)
  414. {
  415. /* NUL pad the remaining n-1 bytes */
  416. while (--n != 0)
  417. {
  418. *d++ = 0;
  419. }
  420. break;
  421. }
  422. } while (--n != 0);
  423. }
  424. return (dst);
  425. }
  426. RTM_EXPORT(rt_strncpy);
  427. /**
  428. * This function will compare two strings with specified maximum length
  429. *
  430. * @param cs the string to be compared
  431. * @param ct the string to be compared
  432. * @param count the maximum compare length
  433. *
  434. * @return the result
  435. */
  436. rt_int32_t rt_strncmp(const char *cs, const char *ct, rt_ubase_t count)
  437. {
  438. register signed char __res = 0;
  439. while (count)
  440. {
  441. if ((__res = *cs - *ct++) != 0 || !*cs++)
  442. {
  443. break;
  444. }
  445. count --;
  446. }
  447. return __res;
  448. }
  449. RTM_EXPORT(rt_strncmp);
  450. /**
  451. * This function will compare two strings without specified length
  452. *
  453. * @param cs the string to be compared
  454. * @param ct the string to be compared
  455. *
  456. * @return the result
  457. */
  458. rt_int32_t rt_strcmp(const char *cs, const char *ct)
  459. {
  460. while (*cs && *cs == *ct)
  461. {
  462. cs++;
  463. ct++;
  464. }
  465. return (*cs - *ct);
  466. }
  467. RTM_EXPORT(rt_strcmp);
  468. /**
  469. * The strnlen() function returns the number of characters in the
  470. * string pointed to by s, excluding the terminating null byte ('\0'),
  471. * but at most maxlen. In doing this, strnlen() looks only at the
  472. * first maxlen characters in the string pointed to by s and never
  473. * beyond s+maxlen.
  474. *
  475. * @param s the string
  476. * @param maxlen the max size
  477. * @return the length of string
  478. */
  479. rt_size_t rt_strnlen(const char *s, rt_ubase_t maxlen)
  480. {
  481. const char *sc = RT_NULL;
  482. for (sc = s; *sc != '\0' && (rt_ubase_t)(sc - s) < maxlen; ++sc) /* nothing */
  483. ;
  484. return sc - s;
  485. }
  486. RTM_EXPORT(rt_strnlen);
  487. /**
  488. * This function will return the length of a string, which terminate will
  489. * null character.
  490. *
  491. * @param s the string
  492. *
  493. * @return the length of string
  494. */
  495. rt_size_t rt_strlen(const char *s)
  496. {
  497. const char *sc = RT_NULL;
  498. for (sc = s; *sc != '\0'; ++sc) /* nothing */
  499. ;
  500. return sc - s;
  501. }
  502. RTM_EXPORT(rt_strlen);
  503. #ifdef RT_USING_HEAP
  504. /**
  505. * This function will duplicate a string.
  506. *
  507. * @param s the string to be duplicated
  508. *
  509. * @return the duplicated string pointer
  510. */
  511. char *rt_strdup(const char *s)
  512. {
  513. rt_size_t len = rt_strlen(s) + 1;
  514. char *tmp = (char *)rt_malloc(len);
  515. if (!tmp)
  516. {
  517. return RT_NULL;
  518. }
  519. rt_memcpy(tmp, s, len);
  520. return tmp;
  521. }
  522. RTM_EXPORT(rt_strdup);
  523. #if defined(__CC_ARM) || defined(__CLANG_ARM)
  524. char *strdup(const char *s) __attribute__((alias("rt_strdup")));
  525. #endif
  526. #endif
  527. /**
  528. * This function will show the version of rt-thread rtos
  529. */
  530. void rt_show_version(void)
  531. {
  532. rt_kprintf("\n \\ | /\n");
  533. #ifdef RT_USING_SMART
  534. rt_kprintf("- RT - Thread Smart Operating System\n");
  535. #else
  536. rt_kprintf("- RT - Thread Operating System\n");
  537. #endif
  538. rt_kprintf(" / | \\ %d.%d.%d build %s\n",
  539. RT_VERSION, RT_SUBVERSION, RT_REVISION, __DATE__);
  540. rt_kprintf(" 2006 - 2020 Copyright by rt-thread team\n");
  541. }
  542. RTM_EXPORT(rt_show_version);
  543. /* private function */
  544. #define _ISDIGIT(c) ((unsigned)((c) - '0') < 10)
  545. #ifdef RT_PRINTF_LONGLONG
  546. rt_inline int divide(long long *n, int base)
  547. {
  548. int res = 0;
  549. /* optimized for processor which does not support divide instructions. */
  550. if (base == 10)
  551. {
  552. res = (int)(((unsigned long long)*n) % 10U);
  553. *n = (long long)(((unsigned long long)*n) / 10U);
  554. }
  555. else
  556. {
  557. res = (int)(((unsigned long long)*n) % 16U);
  558. *n = (long long)(((unsigned long long)*n) / 16U);
  559. }
  560. return res;
  561. }
  562. #else
  563. rt_inline int divide(long *n, int base)
  564. {
  565. int res = 0;
  566. /* optimized for processor which does not support divide instructions. */
  567. if (base == 10)
  568. {
  569. res = (int)(((unsigned long)*n) % 10U);
  570. *n = (long)(((unsigned long)*n) / 10U);
  571. }
  572. else
  573. {
  574. res = (int)(((unsigned long)*n) % 16U);
  575. *n = (long)(((unsigned long)*n) / 16U);
  576. }
  577. return res;
  578. }
  579. #endif
  580. rt_inline int skip_atoi(const char **s)
  581. {
  582. register int i = 0;
  583. while (_ISDIGIT(**s))
  584. {
  585. i = i * 10 + *((*s)++) - '0';
  586. }
  587. return i;
  588. }
  589. #define ZEROPAD (1 << 0) /* pad with zero */
  590. #define SIGN (1 << 1) /* unsigned/signed long */
  591. #define PLUS (1 << 2) /* show plus */
  592. #define SPACE (1 << 3) /* space if plus */
  593. #define LEFT (1 << 4) /* left justified */
  594. #define SPECIAL (1 << 5) /* 0x */
  595. #define LARGE (1 << 6) /* use 'ABCDEF' instead of 'abcdef' */
  596. #ifdef RT_PRINTF_PRECISION
  597. static char *print_number(char *buf,
  598. char *end,
  599. #ifdef RT_PRINTF_LONGLONG
  600. long long num,
  601. #else
  602. long num,
  603. #endif
  604. int base,
  605. int s,
  606. int precision,
  607. int type)
  608. #else
  609. static char *print_number(char *buf,
  610. char *end,
  611. #ifdef RT_PRINTF_LONGLONG
  612. long long num,
  613. #else
  614. long num,
  615. #endif
  616. int base,
  617. int s,
  618. int type)
  619. #endif
  620. {
  621. char c = 0, sign = 0;
  622. #ifdef RT_PRINTF_LONGLONG
  623. char tmp[32] = {0};
  624. #else
  625. char tmp[16] = {0};
  626. #endif
  627. int precision_bak = precision;
  628. const char *digits = RT_NULL;
  629. static const char small_digits[] = "0123456789abcdef";
  630. static const char large_digits[] = "0123456789ABCDEF";
  631. register int i = 0;
  632. register int size = 0;
  633. size = s;
  634. digits = (type & LARGE) ? large_digits : small_digits;
  635. if (type & LEFT)
  636. {
  637. type &= ~ZEROPAD;
  638. }
  639. c = (type & ZEROPAD) ? '0' : ' ';
  640. /* get sign */
  641. sign = 0;
  642. if (type & SIGN)
  643. {
  644. if (num < 0)
  645. {
  646. sign = '-';
  647. num = -num;
  648. }
  649. else if (type & PLUS)
  650. {
  651. sign = '+';
  652. }
  653. else if (type & SPACE)
  654. {
  655. sign = ' ';
  656. }
  657. }
  658. #ifdef RT_PRINTF_SPECIAL
  659. if (type & SPECIAL)
  660. {
  661. if (base == 16)
  662. {
  663. size -= 2;
  664. }
  665. else if (base == 8)
  666. {
  667. size--;
  668. }
  669. }
  670. #endif
  671. i = 0;
  672. if (num == 0)
  673. {
  674. tmp[i++] = '0';
  675. }
  676. else
  677. {
  678. while (num != 0)
  679. {
  680. tmp[i++] = digits[divide(&num, base)];
  681. }
  682. }
  683. #ifdef RT_PRINTF_PRECISION
  684. if (i > precision)
  685. {
  686. precision = i;
  687. }
  688. size -= precision;
  689. #else
  690. size -= i;
  691. #endif
  692. if (!(type & (ZEROPAD | LEFT)))
  693. {
  694. if ((sign) && (size > 0))
  695. {
  696. size--;
  697. }
  698. while (size-- > 0)
  699. {
  700. if (buf < end)
  701. {
  702. *buf = ' ';
  703. }
  704. ++ buf;
  705. }
  706. }
  707. if (sign)
  708. {
  709. if (buf < end)
  710. {
  711. *buf = sign;
  712. }
  713. -- size;
  714. ++ buf;
  715. }
  716. #ifdef RT_PRINTF_SPECIAL
  717. if (type & SPECIAL)
  718. {
  719. if (base == 8)
  720. {
  721. if (buf < end)
  722. {
  723. *buf = '0';
  724. }
  725. ++ buf;
  726. }
  727. else if (base == 16)
  728. {
  729. if (buf < end)
  730. {
  731. *buf = '0';
  732. }
  733. ++ buf;
  734. if (buf < end)
  735. {
  736. *buf = type & LARGE ? 'X' : 'x';
  737. }
  738. ++ buf;
  739. }
  740. }
  741. #endif
  742. /* no align to the left */
  743. if (!(type & LEFT))
  744. {
  745. while (size-- > 0)
  746. {
  747. if (buf < end)
  748. {
  749. *buf = c;
  750. }
  751. ++ buf;
  752. }
  753. }
  754. #ifdef RT_PRINTF_PRECISION
  755. while (i < precision--)
  756. {
  757. if (buf < end)
  758. {
  759. *buf = '0';
  760. }
  761. ++ buf;
  762. }
  763. #endif
  764. /* put number in the temporary buffer */
  765. while (i-- > 0 && (precision_bak != 0))
  766. {
  767. if (buf < end)
  768. {
  769. *buf = tmp[i];
  770. }
  771. ++ buf;
  772. }
  773. while (size-- > 0)
  774. {
  775. if (buf < end)
  776. {
  777. *buf = ' ';
  778. }
  779. ++ buf;
  780. }
  781. return buf;
  782. }
  783. rt_int32_t rt_vsnprintf(char *buf,
  784. rt_size_t size,
  785. const char *fmt,
  786. va_list args)
  787. {
  788. #ifdef RT_PRINTF_LONGLONG
  789. unsigned long long num = 0;
  790. #else
  791. long num = 0;
  792. #endif
  793. int i = 0, len = 0;
  794. char *str = RT_NULL, *end = RT_NULL, c = 0;
  795. const char *s = RT_NULL;
  796. rt_uint8_t base = 0; /* the base of number */
  797. rt_uint8_t flags = 0; /* flags to print number */
  798. rt_uint8_t qualifier = 0; /* 'h', 'l', or 'L' for integer fields */
  799. rt_int32_t field_width = 0; /* width of output field */
  800. #ifdef RT_PRINTF_PRECISION
  801. int precision = 0; /* min. # of digits for integers and max for a string */
  802. #endif
  803. str = buf;
  804. end = buf + size;
  805. /* Make sure end is always >= buf */
  806. if (end < buf)
  807. {
  808. end = ((char *) - 1);
  809. size = end - buf;
  810. }
  811. for (; *fmt ; ++fmt)
  812. {
  813. if (*fmt != '%')
  814. {
  815. if (str < end)
  816. {
  817. *str = *fmt;
  818. }
  819. ++ str;
  820. continue;
  821. }
  822. /* process flags */
  823. flags = 0;
  824. while (1)
  825. {
  826. /* skips the first '%' also */
  827. ++ fmt;
  828. if (*fmt == '-') flags |= LEFT;
  829. else if (*fmt == '+') flags |= PLUS;
  830. else if (*fmt == ' ') flags |= SPACE;
  831. else if (*fmt == '#') flags |= SPECIAL;
  832. else if (*fmt == '0') flags |= ZEROPAD;
  833. else break;
  834. }
  835. /* get field width */
  836. field_width = -1;
  837. if (_ISDIGIT(*fmt))
  838. {
  839. field_width = skip_atoi(&fmt);
  840. }
  841. else if (*fmt == '*')
  842. {
  843. ++ fmt;
  844. /* it's the next argument */
  845. field_width = va_arg(args, int);
  846. if (field_width < 0)
  847. {
  848. field_width = -field_width;
  849. flags |= LEFT;
  850. }
  851. }
  852. #ifdef RT_PRINTF_PRECISION
  853. /* get the precision */
  854. precision = -1;
  855. if (*fmt == '.')
  856. {
  857. ++ fmt;
  858. if (_ISDIGIT(*fmt))
  859. {
  860. precision = skip_atoi(&fmt);
  861. }
  862. else if (*fmt == '*')
  863. {
  864. ++ fmt;
  865. /* it's the next argument */
  866. precision = va_arg(args, int);
  867. }
  868. if (precision < 0)
  869. {
  870. precision = 0;
  871. }
  872. }
  873. #endif
  874. /* get the conversion qualifier */
  875. qualifier = 0;
  876. #ifdef RT_PRINTF_LONGLONG
  877. if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L')
  878. #else
  879. if (*fmt == 'h' || *fmt == 'l')
  880. #endif
  881. {
  882. qualifier = *fmt;
  883. ++ fmt;
  884. #ifdef RT_PRINTF_LONGLONG
  885. if (qualifier == 'l' && *fmt == 'l')
  886. {
  887. qualifier = 'L';
  888. ++ fmt;
  889. }
  890. #endif
  891. }
  892. /* the default base */
  893. base = 10;
  894. switch (*fmt)
  895. {
  896. case 'c':
  897. if (!(flags & LEFT))
  898. {
  899. while (--field_width > 0)
  900. {
  901. if (str < end) *str = ' ';
  902. ++ str;
  903. }
  904. }
  905. /* get character */
  906. c = (rt_uint8_t)va_arg(args, int);
  907. if (str < end)
  908. {
  909. *str = c;
  910. }
  911. ++ str;
  912. /* put width */
  913. while (--field_width > 0)
  914. {
  915. if (str < end) *str = ' ';
  916. ++ str;
  917. }
  918. continue;
  919. case 's':
  920. s = va_arg(args, char *);
  921. if (!s)
  922. {
  923. s = "(NULL)";
  924. }
  925. len = rt_strlen(s);
  926. #ifdef RT_PRINTF_PRECISION
  927. if (precision > 0 && len > precision)
  928. {
  929. len = precision;
  930. }
  931. #endif
  932. if (!(flags & LEFT))
  933. {
  934. while (len < field_width--)
  935. {
  936. if (str < end) *str = ' ';
  937. ++ str;
  938. }
  939. }
  940. for (i = 0; i < len; ++i)
  941. {
  942. if (str < end) *str = *s;
  943. ++ str;
  944. ++ s;
  945. }
  946. while (len < field_width--)
  947. {
  948. if (str < end) *str = ' ';
  949. ++ str;
  950. }
  951. continue;
  952. case 'p':
  953. if (field_width == -1)
  954. {
  955. field_width = sizeof(void *) << 1;
  956. flags |= ZEROPAD;
  957. }
  958. #ifdef RT_PRINTF_PRECISION
  959. str = print_number(str, end,
  960. (long)va_arg(args, void *),
  961. 16, field_width, precision, flags);
  962. #else
  963. str = print_number(str, end,
  964. (long)va_arg(args, void *),
  965. 16, field_width, flags);
  966. #endif
  967. continue;
  968. case '%':
  969. if (str < end)
  970. {
  971. *str = '%';
  972. }
  973. ++ str;
  974. continue;
  975. /* integer number formats - set up the flags and "break" */
  976. case 'o':
  977. base = 8;
  978. break;
  979. case 'X':
  980. flags |= LARGE;
  981. case 'x':
  982. base = 16;
  983. break;
  984. case 'd':
  985. case 'i':
  986. flags |= SIGN;
  987. case 'u':
  988. break;
  989. default:
  990. if (str < end)
  991. {
  992. *str = '%';
  993. }
  994. ++ str;
  995. if (*fmt)
  996. {
  997. if (str < end)
  998. {
  999. *str = *fmt;
  1000. }
  1001. ++ str;
  1002. }
  1003. else
  1004. {
  1005. -- fmt;
  1006. }
  1007. continue;
  1008. }
  1009. #ifdef RT_PRINTF_LONGLONG
  1010. if (qualifier == 'L')
  1011. {
  1012. num = va_arg(args, long long);
  1013. }
  1014. else if (qualifier == 'l')
  1015. #else
  1016. if (qualifier == 'l')
  1017. #endif
  1018. {
  1019. num = va_arg(args, long);
  1020. if (flags & SIGN)
  1021. {
  1022. num = (rt_int32_t)num;
  1023. }
  1024. }
  1025. else if (qualifier == 'h')
  1026. {
  1027. num = (rt_uint16_t)va_arg(args, rt_int32_t);
  1028. if (flags & SIGN)
  1029. {
  1030. num = (rt_int16_t)num;
  1031. }
  1032. }
  1033. else
  1034. {
  1035. num = va_arg(args, long);
  1036. if (flags & SIGN)
  1037. {
  1038. num = (rt_int32_t)num;
  1039. }
  1040. }
  1041. #ifdef RT_PRINTF_PRECISION
  1042. str = print_number(str, end, num, base, field_width, precision, flags);
  1043. #else
  1044. str = print_number(str, end, num, base, field_width, flags);
  1045. #endif
  1046. }
  1047. if (size > 0)
  1048. {
  1049. if (str < end)
  1050. {
  1051. *str = '\0';
  1052. }
  1053. else
  1054. {
  1055. end[-1] = '\0';
  1056. }
  1057. }
  1058. /* the trailing null byte doesn't count towards the total
  1059. * ++str;
  1060. */
  1061. return str - buf;
  1062. }
  1063. RTM_EXPORT(rt_vsnprintf);
  1064. /**
  1065. * This function will fill a formatted string to buffer
  1066. *
  1067. * @param buf the buffer to save formatted string
  1068. * @param size the size of buffer
  1069. * @param fmt the format
  1070. */
  1071. rt_int32_t rt_snprintf(char *buf, rt_size_t size, const char *fmt, ...)
  1072. {
  1073. rt_int32_t n = 0;
  1074. va_list args;
  1075. va_start(args, fmt);
  1076. n = rt_vsnprintf(buf, size, fmt, args);
  1077. va_end(args);
  1078. return n;
  1079. }
  1080. RTM_EXPORT(rt_snprintf);
  1081. /**
  1082. * This function will fill a formatted string to buffer
  1083. *
  1084. * @param buf the buffer to save formatted string
  1085. * @param arg_ptr the arg_ptr
  1086. * @param format the format
  1087. */
  1088. rt_int32_t rt_vsprintf(char *buf, const char *format, va_list arg_ptr)
  1089. {
  1090. return rt_vsnprintf(buf, (rt_size_t) - 1, format, arg_ptr);
  1091. }
  1092. RTM_EXPORT(rt_vsprintf);
  1093. /**
  1094. * This function will fill a formatted string to buffer
  1095. *
  1096. * @param buf the buffer to save formatted string
  1097. * @param format the format
  1098. */
  1099. rt_int32_t rt_sprintf(char *buf, const char *format, ...)
  1100. {
  1101. rt_int32_t n = 0;
  1102. va_list arg_ptr;
  1103. va_start(arg_ptr, format);
  1104. n = rt_vsprintf(buf, format, arg_ptr);
  1105. va_end(arg_ptr);
  1106. return n;
  1107. }
  1108. RTM_EXPORT(rt_sprintf);
  1109. #ifdef RT_USING_CONSOLE
  1110. #ifdef RT_USING_DEVICE
  1111. /**
  1112. * This function returns the device using in console.
  1113. *
  1114. * @return the device using in console or RT_NULL
  1115. */
  1116. rt_device_t rt_console_get_device(void)
  1117. {
  1118. return _console_device;
  1119. }
  1120. RTM_EXPORT(rt_console_get_device);
  1121. /**
  1122. * This function will set a device as console device.
  1123. * After set a device to console, all output of rt_kprintf will be
  1124. * redirected to this new device.
  1125. *
  1126. * @param name the name of new console device
  1127. *
  1128. * @return the old console device handler on successful, or RT_NULL on failure.
  1129. */
  1130. rt_device_t rt_console_set_device(const char *name)
  1131. {
  1132. #ifdef RT_USING_LWP
  1133. rt_device_t new_iodev = RT_NULL, old_iodev = RT_NULL;
  1134. extern void console_init();
  1135. console_init(); /*add line discipline*/
  1136. /* find new console device */
  1137. new_iodev = rt_device_find(name);
  1138. if (new_iodev != RT_NULL)
  1139. {
  1140. if (_console_device != RT_NULL)
  1141. {
  1142. old_iodev = console_set_iodev(new_iodev);
  1143. }
  1144. else
  1145. {
  1146. console_register("console", new_iodev);
  1147. _console_device = rt_device_find("console");
  1148. rt_device_open(_console_device, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_STREAM);
  1149. }
  1150. }
  1151. return old_iodev;
  1152. #else
  1153. rt_device_t new_device, old_device;
  1154. /* save old device */
  1155. old_device = _console_device;
  1156. /* find new console device */
  1157. new_device = rt_device_find(name);
  1158. /* check whether it's a same device */
  1159. if (new_device == old_device) return RT_NULL;
  1160. if (new_device != RT_NULL)
  1161. {
  1162. if (_console_device != RT_NULL)
  1163. {
  1164. /* close old console device */
  1165. rt_device_close(_console_device);
  1166. }
  1167. /* set new console device */
  1168. rt_device_open(new_device, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_STREAM);
  1169. _console_device = new_device;
  1170. }
  1171. return old_device;
  1172. #endif
  1173. }
  1174. RTM_EXPORT(rt_console_set_device);
  1175. #endif
  1176. RT_WEAK void rt_hw_console_output(const char *str)
  1177. {
  1178. /* empty console output */
  1179. }
  1180. RTM_EXPORT(rt_hw_console_output);
  1181. /**
  1182. * This function will put string to the console.
  1183. *
  1184. * @param str the string output to the console.
  1185. */
  1186. void rt_kputs(const char *str)
  1187. {
  1188. if (!str)
  1189. {
  1190. return;
  1191. }
  1192. #ifdef RT_USING_DEVICE
  1193. if (_console_device == RT_NULL)
  1194. {
  1195. rt_hw_console_output(str);
  1196. }
  1197. else
  1198. {
  1199. rt_uint16_t old_flag = _console_device->open_flag;
  1200. _console_device->open_flag |= RT_DEVICE_FLAG_STREAM;
  1201. rt_device_write(_console_device, 0, str, rt_strlen(str));
  1202. _console_device->open_flag = old_flag;
  1203. }
  1204. #else
  1205. rt_hw_console_output(str);
  1206. #endif
  1207. }
  1208. /**
  1209. * This function will print a formatted string on system console
  1210. *
  1211. * @param fmt the format
  1212. */
  1213. void rt_kprintf(const char *fmt, ...)
  1214. {
  1215. va_list args;
  1216. rt_size_t length = 0;
  1217. static char rt_log_buf[RT_CONSOLEBUF_SIZE];
  1218. va_start(args, fmt);
  1219. /* the return value of vsnprintf is the number of bytes that would be
  1220. * written to buffer had if the size of the buffer been sufficiently
  1221. * large excluding the terminating null byte. If the output string
  1222. * would be larger than the rt_log_buf, we have to adjust the output
  1223. * length. */
  1224. length = rt_vsnprintf(rt_log_buf, sizeof(rt_log_buf) - 1, fmt, args);
  1225. if (length > RT_CONSOLEBUF_SIZE - 1)
  1226. {
  1227. length = RT_CONSOLEBUF_SIZE - 1;
  1228. }
  1229. #ifdef RT_USING_DEVICE
  1230. if (_console_device == RT_NULL)
  1231. {
  1232. rt_hw_console_output(rt_log_buf);
  1233. }
  1234. else
  1235. {
  1236. rt_uint16_t old_flag = _console_device->open_flag;
  1237. _console_device->open_flag |= RT_DEVICE_FLAG_STREAM;
  1238. rt_device_write(_console_device, 0, rt_log_buf, length);
  1239. _console_device->open_flag = old_flag;
  1240. }
  1241. #else
  1242. rt_hw_console_output(rt_log_buf);
  1243. #endif
  1244. va_end(args);
  1245. }
  1246. RTM_EXPORT(rt_kprintf);
  1247. #endif
  1248. #ifdef RT_USING_HEAP
  1249. /**
  1250. * This function allocates a memory block, which address is aligned to the
  1251. * specified alignment size.
  1252. *
  1253. * @param size the allocated memory block size
  1254. * @param align the alignment size
  1255. *
  1256. * @return the allocated memory block on successful, otherwise returns RT_NULL
  1257. */
  1258. void *rt_malloc_align(rt_size_t size, rt_size_t align)
  1259. {
  1260. void *ptr = RT_NULL;
  1261. void *align_ptr = RT_NULL;
  1262. int uintptr_size = 0;
  1263. rt_size_t align_size = 0;
  1264. /* sizeof pointer */
  1265. uintptr_size = sizeof(void*);
  1266. uintptr_size -= 1;
  1267. /* align the alignment size to uintptr size byte */
  1268. align = ((align + uintptr_size) & ~uintptr_size);
  1269. /* get total aligned size */
  1270. align_size = ((size + uintptr_size) & ~uintptr_size) + align;
  1271. /* allocate memory block from heap */
  1272. ptr = rt_malloc(align_size);
  1273. if (ptr != RT_NULL)
  1274. {
  1275. /* the allocated memory block is aligned */
  1276. if (((rt_ubase_t)ptr & (align - 1)) == 0)
  1277. {
  1278. align_ptr = (void *)((rt_ubase_t)ptr + align);
  1279. }
  1280. else
  1281. {
  1282. align_ptr = (void *)(((rt_ubase_t)ptr + (align - 1)) & ~(align - 1));
  1283. }
  1284. /* set the pointer before alignment pointer to the real pointer */
  1285. *((rt_ubase_t *)((rt_ubase_t)align_ptr - sizeof(void *))) = (rt_ubase_t)ptr;
  1286. ptr = align_ptr;
  1287. }
  1288. return ptr;
  1289. }
  1290. RTM_EXPORT(rt_malloc_align);
  1291. /**
  1292. * This function release the memory block, which is allocated by
  1293. * rt_malloc_align function and address is aligned.
  1294. *
  1295. * @param ptr the memory block pointer
  1296. */
  1297. void rt_free_align(void *ptr)
  1298. {
  1299. void *real_ptr = RT_NULL;
  1300. real_ptr = (void *) * (rt_ubase_t *)((rt_ubase_t)ptr - sizeof(void *));
  1301. rt_free(real_ptr);
  1302. }
  1303. RTM_EXPORT(rt_free_align);
  1304. #endif
  1305. #ifndef RT_USING_CPU_FFS
  1306. const rt_uint8_t __lowest_bit_bitmap[] =
  1307. {
  1308. /* 00 */ 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  1309. /* 10 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  1310. /* 20 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  1311. /* 30 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  1312. /* 40 */ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  1313. /* 50 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  1314. /* 60 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  1315. /* 70 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  1316. /* 80 */ 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  1317. /* 90 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  1318. /* A0 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  1319. /* B0 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  1320. /* C0 */ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  1321. /* D0 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  1322. /* E0 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  1323. /* F0 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
  1324. };
  1325. /**
  1326. * This function finds the first bit set (beginning with the least significant bit)
  1327. * in value and return the index of that bit.
  1328. *
  1329. * Bits are numbered starting at 1 (the least significant bit). A return value of
  1330. * zero from any of these functions means that the argument was zero.
  1331. *
  1332. * @return return the index of the first bit set. If value is 0, then this function
  1333. * shall return 0.
  1334. */
  1335. int __rt_ffs(int value)
  1336. {
  1337. if (value == 0)
  1338. {
  1339. return 0;
  1340. }
  1341. if (value & 0xff)
  1342. {
  1343. return __lowest_bit_bitmap[value & 0xff] + 1;
  1344. }
  1345. if (value & 0xff00)
  1346. {
  1347. return __lowest_bit_bitmap[(value & 0xff00) >> 8] + 9;
  1348. }
  1349. if (value & 0xff0000)
  1350. {
  1351. return __lowest_bit_bitmap[(value & 0xff0000) >> 16] + 17;
  1352. }
  1353. return __lowest_bit_bitmap[(value & 0xff000000) >> 24] + 25;
  1354. }
  1355. #endif
  1356. #ifdef RT_DEBUG
  1357. /* RT_ASSERT(EX)'s hook */
  1358. void (*rt_assert_hook)(const char *ex, const char *func, rt_size_t line);
  1359. /**
  1360. * This function will set a hook function to RT_ASSERT(EX). It will run when the expression is false.
  1361. *
  1362. * @param hook the hook function
  1363. */
  1364. void rt_assert_set_hook(void (*hook)(const char *ex, const char *func, rt_size_t line))
  1365. {
  1366. rt_assert_hook = hook;
  1367. }
  1368. /**
  1369. * The RT_ASSERT function.
  1370. *
  1371. * @param ex the assertion condition string
  1372. * @param func the function name when assertion.
  1373. * @param line the file line number when assertion.
  1374. */
  1375. void rt_assert_handler(const char *ex_string, const char *func, rt_size_t line)
  1376. {
  1377. volatile char dummy = 0;
  1378. if (rt_assert_hook == RT_NULL)
  1379. {
  1380. #ifdef RT_USING_MODULE
  1381. if (dlmodule_self())
  1382. {
  1383. /* close assertion module */
  1384. dlmodule_exit(-1);
  1385. }
  1386. else
  1387. #endif
  1388. {
  1389. rt_kprintf("(%s) assertion failed at function:%s, line number:%d \n", ex_string, func, line);
  1390. while (dummy == 0);
  1391. }
  1392. }
  1393. else
  1394. {
  1395. rt_assert_hook(ex_string, func, line);
  1396. }
  1397. }
  1398. RTM_EXPORT(rt_assert_handler);
  1399. #endif /* RT_DEBUG */
  1400. #if !defined (RT_USING_NEWLIB) && defined (RT_USING_MINILIBC) && defined (__GNUC__)
  1401. #include <sys/types.h>
  1402. void *memcpy(void *dest, const void *src, size_t n) __attribute__((weak, alias("rt_memcpy")));
  1403. void *memset(void *s, int c, size_t n) __attribute__((weak, alias("rt_memset")));
  1404. void *memmove(void *dest, const void *src, size_t n) __attribute__((weak, alias("rt_memmove")));
  1405. int memcmp(const void *s1, const void *s2, size_t n) __attribute__((weak, alias("rt_memcmp")));
  1406. size_t strlen(const char *s) __attribute__((weak, alias("rt_strlen")));
  1407. char *strstr(const char *s1, const char *s2) __attribute__((weak, alias("rt_strstr")));
  1408. int strcasecmp(const char *a, const char *b) __attribute__((weak, alias("rt_strcasecmp")));
  1409. char *strncpy(char *dest, const char *src, size_t n) __attribute__((weak, alias("rt_strncpy")));
  1410. int strncmp(const char *cs, const char *ct, size_t count) __attribute__((weak, alias("rt_strncmp")));
  1411. #ifdef RT_USING_HEAP
  1412. char *strdup(const char *s) __attribute__((weak, alias("rt_strdup")));
  1413. #endif
  1414. int sprintf(char *buf, const char *format, ...) __attribute__((weak, alias("rt_sprintf")));
  1415. int snprintf(char *buf, rt_size_t size, const char *fmt, ...) __attribute__((weak, alias("rt_snprintf")));
  1416. int vsprintf(char *buf, const char *format, va_list arg_ptr) __attribute__((weak, alias("rt_vsprintf")));
  1417. #endif
  1418. /**@}*/