kservice.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020
  1. /*
  2. * File : kservice.c
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
  5. *
  6. * The license and distribution terms for this file may be
  7. * found in the file LICENSE in this distribution or at
  8. * http://www.rt-thread.org/license/LICENSE
  9. *
  10. * Change Logs:
  11. * Date Author Notes
  12. * 2006-03-16 Bernard the first version
  13. * 2006-05-25 Bernard rewrite vsprintf
  14. * 2006-08-10 Bernard add rt_show_version
  15. * 2010-03-17 Bernard remove rt_strlcpy function
  16. * fix gcc compiling issue.
  17. * 2010-04-15 Bernard remove weak definition on ICCM16C compiler
  18. */
  19. #include <rtthread.h>
  20. #include <rthw.h>
  21. /**
  22. * @addtogroup KernelService
  23. */
  24. /*@{*/
  25. #ifndef RT_USING_NEWLIB
  26. /* global errno in RT-Thread*/
  27. int errno;
  28. #else
  29. #include <errno.h>
  30. #endif
  31. #if defined(RT_USING_DEVICE) && defined(RT_USING_CONSOLE)
  32. static rt_device_t _console_device = RT_NULL;
  33. #endif
  34. /*
  35. * This function will get errno
  36. *
  37. * @return errno
  38. */
  39. rt_err_t rt_get_errno(void)
  40. {
  41. rt_thread_t tid;
  42. RT_DEBUG_NOT_REENT
  43. tid = rt_thread_self();
  44. if (tid == RT_NULL) return errno;
  45. return tid->error;
  46. }
  47. /*
  48. * This function will set errno
  49. *
  50. * @param error the errno shall be set
  51. */
  52. void rt_set_errno(rt_err_t error)
  53. {
  54. rt_thread_t tid;
  55. RT_DEBUG_NOT_REENT
  56. tid = rt_thread_self();
  57. if (tid == RT_NULL) { errno = error; return; }
  58. tid->error = error;
  59. }
  60. /**
  61. * This function will set the content of memory to specified value
  62. *
  63. * @param s the address of source memory
  64. * @param c the value shall be set in content
  65. * @param count the copied length
  66. *
  67. * @return the address of source memory
  68. *
  69. */
  70. void *rt_memset(void * s, int c, rt_ubase_t count)
  71. {
  72. #ifdef RT_TINY_SIZE
  73. char *xs = (char *) s;
  74. while (count--)
  75. *xs++ = c;
  76. return s;
  77. #else
  78. #define LBLOCKSIZE (sizeof(rt_int32_t))
  79. #define UNALIGNED(X) ((rt_int32_t)X & (LBLOCKSIZE - 1))
  80. #define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE)
  81. int i;
  82. char *m = (char *)s;
  83. rt_uint32_t buffer;
  84. rt_uint32_t *aligned_addr;
  85. rt_uint32_t d = c & 0xff;
  86. if (!TOO_SMALL (count) && !UNALIGNED (s))
  87. {
  88. /* If we get this far, we know that n is large and m is word-aligned. */
  89. aligned_addr = (rt_uint32_t*)s;
  90. /* Store D into each char sized location in BUFFER so that
  91. * we can set large blocks quickly.
  92. */
  93. if (LBLOCKSIZE == 4)
  94. {
  95. buffer = (d << 8) | d;
  96. buffer |= (buffer << 16);
  97. }
  98. else
  99. {
  100. buffer = 0;
  101. for (i = 0; i < LBLOCKSIZE; i++)
  102. buffer = (buffer << 8) | d;
  103. }
  104. while (count >= LBLOCKSIZE*4)
  105. {
  106. *aligned_addr++ = buffer;
  107. *aligned_addr++ = buffer;
  108. *aligned_addr++ = buffer;
  109. *aligned_addr++ = buffer;
  110. count -= 4*LBLOCKSIZE;
  111. }
  112. while (count >= LBLOCKSIZE)
  113. {
  114. *aligned_addr++ = buffer;
  115. count -= LBLOCKSIZE;
  116. }
  117. /* Pick up the remainder with a bytewise loop. */
  118. m = (char*)aligned_addr;
  119. }
  120. while (count--)
  121. {
  122. *m++ = (char)d;
  123. }
  124. return s;
  125. #undef LBLOCKSIZE
  126. #undef UNALIGNED
  127. #undef TOO_SMALL
  128. #endif
  129. }
  130. /**
  131. * This function will copy memory content from source address to destination
  132. * address.
  133. *
  134. * @param dst the address of destination memory
  135. * @param src the address of source memory
  136. * @param count the copied length
  137. *
  138. * @return the address of destination memory
  139. *
  140. */
  141. void *rt_memcpy(void * dst, const void *src, rt_ubase_t count)
  142. {
  143. #ifdef RT_TINY_SIZE
  144. char *tmp = (char *) dst, *s = (char *) src;
  145. while (count--)
  146. *tmp++ = *s++;
  147. return dst;
  148. #else
  149. #define UNALIGNED(X, Y) \
  150. (((rt_int32_t)X & (sizeof (rt_int32_t) - 1)) | ((rt_int32_t)Y & (sizeof (rt_int32_t) - 1)))
  151. #define BIGBLOCKSIZE (sizeof (rt_int32_t) << 2)
  152. #define LITTLEBLOCKSIZE (sizeof (rt_int32_t))
  153. #define TOO_SMALL(LEN) ((LEN) < BIGBLOCKSIZE)
  154. char *dst_ptr = (char*)dst;
  155. char *src_ptr = (char*)src;
  156. rt_int32_t *aligned_dst;
  157. rt_int32_t *aligned_src;
  158. int len = count;
  159. /* If the size is small, or either SRC or DST is unaligned,
  160. then punt into the byte copy loop. This should be rare. */
  161. if (!TOO_SMALL(len) && !UNALIGNED (src_ptr, dst_ptr))
  162. {
  163. aligned_dst = (rt_int32_t*)dst_ptr;
  164. aligned_src = (rt_int32_t*)src_ptr;
  165. /* Copy 4X long words at a time if possible. */
  166. while (len >= BIGBLOCKSIZE)
  167. {
  168. *aligned_dst++ = *aligned_src++;
  169. *aligned_dst++ = *aligned_src++;
  170. *aligned_dst++ = *aligned_src++;
  171. *aligned_dst++ = *aligned_src++;
  172. len -= BIGBLOCKSIZE;
  173. }
  174. /* Copy one long word at a time if possible. */
  175. while (len >= LITTLEBLOCKSIZE)
  176. {
  177. *aligned_dst++ = *aligned_src++;
  178. len -= LITTLEBLOCKSIZE;
  179. }
  180. /* Pick up any residual with a byte copier. */
  181. dst_ptr = (char*)aligned_dst;
  182. src_ptr = (char*)aligned_src;
  183. }
  184. while (len--)
  185. *dst_ptr++ = *src_ptr++;
  186. return dst;
  187. #undef UNALIGNED
  188. #undef BIGBLOCKSIZE
  189. #undef LITTLEBLOCKSIZE
  190. #undef TOO_SMALL
  191. #endif
  192. }
  193. /**
  194. * This function will move memory content from source address to destination
  195. * address.
  196. *
  197. * @param dest the address of destination memory
  198. * @param src the address of source memory
  199. * @param n the copied length
  200. *
  201. * @return the address of destination memory
  202. *
  203. */
  204. void* rt_memmove(void *dest, const void *src, rt_ubase_t n)
  205. {
  206. char *tmp = (char *) dest, *s = (char *) src;
  207. if (s < tmp && tmp < s + n)
  208. {
  209. tmp+=n;
  210. s+=n;
  211. while (n--)
  212. *tmp-- = *s--;
  213. }
  214. else
  215. {
  216. while (n--)
  217. *tmp++ = *s++;
  218. }
  219. return dest;
  220. }
  221. /**
  222. * memcmp - Compare two areas of memory
  223. * @param cs: One area of memory
  224. * @param ct: Another area of memory
  225. * @param count: The size of the area.
  226. */
  227. rt_int32_t rt_memcmp(const void * cs,const void * ct, rt_ubase_t count)
  228. {
  229. const unsigned char *su1, *su2;
  230. int res = 0;
  231. for( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
  232. if ((res = *su1 - *su2) != 0)
  233. break;
  234. return res;
  235. }
  236. /**
  237. * This function will return the first occurrence of a string.
  238. *
  239. * @param s1 the source string
  240. * @param s2 the find string
  241. *
  242. * @return the first occurrence of a s2 in s1, or RT_NULL if no found.
  243. */
  244. char * rt_strstr(const char * s1,const char * s2)
  245. {
  246. int l1, l2;
  247. l2 = rt_strlen(s2);
  248. if (!l2)
  249. return (char *) s1;
  250. l1 = rt_strlen(s1);
  251. while (l1 >= l2)
  252. {
  253. l1--;
  254. if (!rt_memcmp(s1,s2,l2))
  255. return (char *) s1;
  256. s1++;
  257. }
  258. return RT_NULL;
  259. }
  260. /**
  261. * This function will compare two strings while ignoring differences in case
  262. *
  263. * @param a the string to be compared
  264. * @param b the string to be compared
  265. *
  266. * @return the result
  267. */
  268. rt_uint32_t rt_strcasecmp(const char *a, const char *b)
  269. {
  270. int ca, cb;
  271. do
  272. {
  273. ca = *a++ & 0xff;
  274. cb = *b++ & 0xff;
  275. if (ca >= 'A' && ca <= 'Z')
  276. ca += 'a' - 'A';
  277. if (cb >= 'A' && cb <= 'Z')
  278. cb += 'a' - 'A';
  279. }
  280. while (ca == cb && ca != '\0');
  281. return ca - cb;
  282. }
  283. /**
  284. * This function will copy string no more than n bytes.
  285. *
  286. * @param dest the string to copy
  287. * @param src the string to be copied
  288. * @param n the maximum copied length
  289. *
  290. * @return the result
  291. */
  292. char *rt_strncpy(char *dest, const char *src, rt_ubase_t n)
  293. {
  294. char *tmp = (char *) dest, *s = (char *) src;
  295. while(n--)
  296. *tmp++ = *s++;
  297. return dest;
  298. }
  299. /**
  300. * This function will compare two strings with specified maximum length
  301. *
  302. * @param cs the string to be compared
  303. * @param ct the string to be compared
  304. * @param count the maximum compare length
  305. *
  306. * @return the result
  307. */
  308. rt_ubase_t rt_strncmp(const char * cs, const char * ct, rt_ubase_t count)
  309. {
  310. register signed char __res = 0;
  311. while (count)
  312. {
  313. if ((__res = *cs - *ct++) != 0 || !*cs++)
  314. break;
  315. count--;
  316. }
  317. return __res;
  318. }
  319. /**
  320. * This function will compare two strings without specified length
  321. *
  322. * @param cs the string to be compared
  323. * @param ct the string to be compared
  324. *
  325. * @return the result
  326. */
  327. rt_ubase_t rt_strcmp (const char *cs, const char *ct)
  328. {
  329. while (*cs && *cs == *ct)
  330. cs++, ct++;
  331. return (*cs - *ct);
  332. }
  333. /**
  334. * This function will return the length of a string, which terminate will
  335. * null character.
  336. *
  337. * @param s the string
  338. *
  339. * @return the length of string
  340. */
  341. rt_ubase_t rt_strlen(const char *s)
  342. {
  343. const char *sc;
  344. for (sc = s; *sc != '\0'; ++sc) /* nothing */
  345. ;
  346. return sc - s;
  347. }
  348. #ifdef RT_USING_HEAP
  349. /**
  350. * This function will duplicate a string.
  351. *
  352. * @param s the string to be duplicated
  353. *
  354. * @return the duplicated string pointer
  355. */
  356. char *rt_strdup(const char *s)
  357. {
  358. rt_size_t len = rt_strlen(s) + 1;
  359. char *tmp = (char *)rt_malloc(len);
  360. if(!tmp) return RT_NULL;
  361. rt_memcpy(tmp, s, len);
  362. return tmp;
  363. }
  364. #endif
  365. /**
  366. * This function will show the version of rt-thread rtos
  367. */
  368. void rt_show_version()
  369. {
  370. rt_kprintf("\n \\ | /\n");
  371. rt_kprintf("- RT - Thread Operating System\n");
  372. rt_kprintf(" / | \\ 0.%d.%d build %s\n", RT_VERSION, RT_SUBVERSION, __DATE__);
  373. rt_kprintf(" 2006 - 2011 Copyright by rt-thread team\n");
  374. }
  375. /* private function */
  376. #define isdigit(c) ((unsigned)((c) - '0') < 10)
  377. rt_inline rt_int32_t divide(rt_int32_t *n, rt_int32_t base)
  378. {
  379. rt_int32_t res;
  380. /* optimized for processor which does not support divide instructions. */
  381. if (base == 10)
  382. {
  383. res = ((rt_uint32_t)*n) % 10U;
  384. *n = ((rt_uint32_t)*n) / 10U;
  385. }
  386. else
  387. {
  388. res = ((rt_uint32_t)*n) % 16U;
  389. *n = ((rt_uint32_t)*n) / 16U;
  390. }
  391. return res;
  392. }
  393. rt_inline int skip_atoi(const char **s)
  394. {
  395. register int i=0;
  396. while (isdigit(**s)) i = i*10 + *((*s)++) - '0';
  397. return i;
  398. }
  399. #define ZEROPAD (1 << 0) /* pad with zero */
  400. #define SIGN (1 << 1) /* unsigned/signed long */
  401. #define PLUS (1 << 2) /* show plus */
  402. #define SPACE (1 << 3) /* space if plus */
  403. #define LEFT (1 << 4) /* left justified */
  404. #define SPECIAL (1 << 5) /* 0x */
  405. #define LARGE (1 << 6) /* use 'ABCDEF' instead of 'abcdef' */
  406. #ifdef RT_PRINTF_PRECISION
  407. static char *print_number(char * buf, char * end, long num, int base, int s, int precision, int type)
  408. #else
  409. static char *print_number(char * buf, char * end, long num, int base, int s, int type)
  410. #endif
  411. {
  412. char c, sign;
  413. #ifdef RT_PRINTF_LONGLONG
  414. char tmp[32];
  415. #else
  416. char tmp[16];
  417. #endif
  418. const char *digits;
  419. static const char small_digits[] = "0123456789abcdef";
  420. static const char large_digits[] = "0123456789ABCDEF";
  421. register int i;
  422. register int size;
  423. size = s;
  424. digits = (type & LARGE) ? large_digits : small_digits;
  425. if (type & LEFT) type &= ~ZEROPAD;
  426. c = (type & ZEROPAD) ? '0' : ' ';
  427. /* get sign */
  428. sign = 0;
  429. if (type & SIGN)
  430. {
  431. if (num < 0)
  432. {
  433. sign = '-';
  434. num = -num;
  435. }
  436. else if (type & PLUS) sign = '+';
  437. else if (type & SPACE) sign = ' ';
  438. }
  439. #ifdef RT_PRINTF_SPECIAL
  440. if (type & SPECIAL)
  441. {
  442. if (base == 16) size -= 2;
  443. else if (base == 8) size--;
  444. }
  445. #endif
  446. i = 0;
  447. if (num == 0) tmp[i++]='0';
  448. else
  449. {
  450. while (num != 0) tmp[i++] = digits[divide(&num, base)];
  451. }
  452. #ifdef RT_PRINTF_PRECISION
  453. if (i > precision) precision = i;
  454. size -= precision;
  455. #else
  456. size -= i;
  457. #endif
  458. if (!(type&(ZEROPAD | LEFT)))
  459. {
  460. while(size-->0)
  461. {
  462. if (buf <= end) *buf = ' ';
  463. ++buf;
  464. }
  465. }
  466. if (sign)
  467. {
  468. if (buf <= end)
  469. {
  470. *buf = sign;
  471. --size;
  472. }
  473. ++buf;
  474. }
  475. #ifdef RT_PRINTF_SPECIAL
  476. if (type & SPECIAL)
  477. {
  478. if (base==8)
  479. {
  480. if (buf <= end) *buf = '0';
  481. ++buf;
  482. }
  483. else if (base==16)
  484. {
  485. if (buf <= end) *buf = '0';
  486. ++buf;
  487. if (buf <= end)
  488. {
  489. *buf = type & LARGE? 'X' : 'x';
  490. }
  491. ++buf;
  492. }
  493. }
  494. #endif
  495. /* no align to the left */
  496. if (!(type & LEFT))
  497. {
  498. while (size-- > 0)
  499. {
  500. if (buf <= end) *buf = c;
  501. ++buf;
  502. }
  503. }
  504. #ifdef RT_PRINTF_PRECISION
  505. while (i < precision--)
  506. {
  507. if (buf <= end) *buf = '0';
  508. ++buf;
  509. }
  510. #endif
  511. /* put number in the temporary buffer */
  512. while (i-- > 0)
  513. {
  514. if (buf <= end) *buf = tmp[i];
  515. ++buf;
  516. }
  517. while (size-- > 0)
  518. {
  519. if (buf <= end) *buf = ' ';
  520. ++buf;
  521. }
  522. return buf;
  523. }
  524. static rt_int32_t vsnprintf(char *buf, rt_size_t size, const char *fmt, va_list args)
  525. {
  526. #ifdef RT_PRINTF_LONGLONG
  527. unsigned long long num;
  528. #else
  529. rt_uint32_t num;
  530. #endif
  531. int i, len;
  532. char *str, *end, c;
  533. const char *s;
  534. rt_uint8_t base; /* the base of number */
  535. rt_uint8_t flags; /* flags to print number */
  536. rt_uint8_t qualifier; /* 'h', 'l', or 'L' for integer fields */
  537. rt_int32_t field_width; /* width of output field */
  538. #ifdef RT_PRINTF_PRECISION
  539. int precision; /* min. # of digits for integers and max for a string */
  540. #endif
  541. str = buf;
  542. end = buf + size - 1;
  543. /* Make sure end is always >= buf */
  544. if (end < buf)
  545. {
  546. end = ((char *)-1);
  547. size = end - buf;
  548. }
  549. for (; *fmt ; ++fmt)
  550. {
  551. if (*fmt != '%')
  552. {
  553. if (str <= end) *str = *fmt;
  554. ++str;
  555. continue;
  556. }
  557. /* process flags */
  558. flags = 0;
  559. while(1)
  560. {
  561. /* skips the first '%' also */
  562. ++fmt;
  563. if (*fmt == '-') flags |= LEFT;
  564. else if (*fmt == '+') flags |= PLUS;
  565. else if (*fmt == ' ') flags |= SPACE;
  566. else if (*fmt == '#') flags |= SPECIAL;
  567. else if (*fmt == '0') flags |= ZEROPAD;
  568. else break;
  569. }
  570. /* get field width */
  571. field_width = -1;
  572. if (isdigit(*fmt)) field_width = skip_atoi(&fmt);
  573. else if (*fmt == '*')
  574. {
  575. ++fmt;
  576. /* it's the next argument */
  577. field_width = va_arg(args, int);
  578. if (field_width < 0)
  579. {
  580. field_width = -field_width;
  581. flags |= LEFT;
  582. }
  583. }
  584. #ifdef RT_PRINTF_PRECISION
  585. /* get the precision */
  586. precision = -1;
  587. if (*fmt == '.')
  588. {
  589. ++fmt;
  590. if (isdigit(*fmt)) precision = skip_atoi(&fmt);
  591. else if (*fmt == '*')
  592. {
  593. ++fmt;
  594. /* it's the next argument */
  595. precision = va_arg(args, int);
  596. }
  597. if (precision < 0) precision = 0;
  598. }
  599. #endif
  600. /* get the conversion qualifier */
  601. qualifier = 0;
  602. if (*fmt == 'h' || *fmt == 'l'
  603. #ifdef RT_PRINTF_LONGLONG
  604. || *fmt == 'L'
  605. #endif
  606. )
  607. {
  608. qualifier = *fmt;
  609. ++fmt;
  610. #ifdef RT_PRINTF_LONGLONG
  611. if (qualifier == 'l' && *fmt == 'l')
  612. {
  613. qualifier = 'L';
  614. ++fmt;
  615. }
  616. #endif
  617. }
  618. /* the default base */
  619. base = 10;
  620. switch (*fmt)
  621. {
  622. case 'c':
  623. if (!(flags & LEFT))
  624. {
  625. while (--field_width > 0)
  626. {
  627. if (str <= end) *str = ' ';
  628. ++str;
  629. }
  630. }
  631. /* get character */
  632. c = (rt_uint8_t) va_arg(args, int);
  633. if (str <= end) *str = c;
  634. ++str;
  635. /* put width */
  636. while (--field_width > 0)
  637. {
  638. if (str <= end) *str = ' ';
  639. ++str;
  640. }
  641. continue;
  642. case 's':
  643. s = va_arg(args, char *);
  644. if (!s) s = "(NULL)";
  645. len = rt_strlen(s);
  646. #ifdef RT_PRINTF_PRECISION
  647. if (precision > 0 && len > precision) len = precision;
  648. #endif
  649. if (!(flags & LEFT))
  650. {
  651. while (len < field_width--)
  652. {
  653. if (str <= end) *str = ' ';
  654. ++str;
  655. }
  656. }
  657. for (i = 0; i < len; ++i)
  658. {
  659. if (str <= end) *str = *s;
  660. ++str;
  661. ++s;
  662. }
  663. while (len < field_width--)
  664. {
  665. if (str <= end) *str = ' ';
  666. ++str;
  667. }
  668. continue;
  669. case 'p':
  670. if (field_width == -1)
  671. {
  672. field_width = sizeof(void *) << 1;
  673. flags |= ZEROPAD;
  674. }
  675. #ifdef RT_PRINTF_PRECISION
  676. str = print_number(str, end,
  677. (long) va_arg(args, void *),
  678. 16, field_width, precision, flags);
  679. #else
  680. str = print_number(str, end,
  681. (long) va_arg(args, void *),
  682. 16, field_width, flags);
  683. #endif
  684. continue;
  685. case '%':
  686. if (str <= end) *str = '%';
  687. ++str;
  688. continue;
  689. /* integer number formats - set up the flags and "break" */
  690. case 'o':
  691. base = 8;
  692. break;
  693. case 'X':
  694. flags |= LARGE;
  695. case 'x':
  696. base = 16;
  697. break;
  698. case 'd':
  699. case 'i':
  700. flags |= SIGN;
  701. case 'u':
  702. break;
  703. default:
  704. if (str <= end) *str = '%';
  705. ++str;
  706. if (*fmt)
  707. {
  708. if (str <= end) *str = *fmt;
  709. ++str;
  710. }
  711. else
  712. {
  713. --fmt;
  714. }
  715. continue;
  716. }
  717. #ifdef RT_PRINTF_LONGLONG
  718. if (qualifier == 'L') num = va_arg(args, long long);
  719. else if (qualifier == 'l')
  720. #else
  721. if (qualifier == 'l')
  722. #endif
  723. {
  724. num = va_arg(args, rt_uint32_t);
  725. if (flags & SIGN) num = (rt_int32_t) num;
  726. }
  727. else if (qualifier == 'h')
  728. {
  729. num = (rt_uint16_t) va_arg(args, rt_int32_t);
  730. if (flags & SIGN) num = (rt_int16_t) num;
  731. }
  732. else
  733. {
  734. num = va_arg(args, rt_uint32_t);
  735. if (flags & SIGN) num = (rt_int32_t) num;
  736. }
  737. #ifdef RT_PRINTF_PRECISION
  738. str = print_number(str, end, num, base, field_width, precision, flags);
  739. #else
  740. str = print_number(str, end, num, base, field_width, flags);
  741. #endif
  742. }
  743. if (str <= end) *str = '\0';
  744. else *end = '\0';
  745. /* the trailing null byte doesn't count towards the total
  746. * ++str;
  747. */
  748. return str-buf;
  749. }
  750. /**
  751. * This function will fill a formatted string to buffer
  752. *
  753. * @param buf the buffer to save formatted string
  754. * @param size the size of buffer
  755. * @param fmt the format
  756. */
  757. rt_int32_t rt_snprintf(char *buf, rt_size_t size, const char *fmt, ...)
  758. {
  759. rt_int32_t n;
  760. va_list args;
  761. va_start(args, fmt);
  762. n = vsnprintf(buf, size, fmt, args);
  763. va_end(args);
  764. return n;
  765. }
  766. /**
  767. * This function will fill a formatted string to buffer
  768. *
  769. * @param buf the buffer to save formatted string
  770. * @param arg_ptr the arg_ptr
  771. * @param format the format
  772. */
  773. rt_int32_t rt_vsprintf(char *buf, const char *format, va_list arg_ptr)
  774. {
  775. return vsnprintf(buf, (rt_size_t) -1, format, arg_ptr);
  776. }
  777. /**
  778. * This function will fill a formatted string to buffer
  779. *
  780. * @param buf the buffer to save formatted string
  781. * @param format the format
  782. */
  783. rt_int32_t rt_sprintf(char *buf ,const char *format,...)
  784. {
  785. rt_int32_t n;
  786. va_list arg_ptr;
  787. va_start(arg_ptr, format);
  788. n = rt_vsprintf(buf ,format,arg_ptr);
  789. va_end (arg_ptr);
  790. return n;
  791. }
  792. #ifdef RT_USING_CONSOLE
  793. #ifdef RT_USING_DEVICE
  794. /**
  795. * This function will set a device as console device.
  796. * After set a device to console, all output of rt_kprintf will be
  797. * redirected to this new device.
  798. *
  799. * @param name the name of new console device
  800. *
  801. * @return the old console device handler
  802. */
  803. rt_device_t rt_console_set_device(const char* name)
  804. {
  805. rt_device_t new, old;
  806. /* save old device */
  807. old = _console_device;
  808. /* find new console device */
  809. new = rt_device_find(name);
  810. if (new != RT_NULL)
  811. {
  812. if (_console_device != RT_NULL)
  813. {
  814. /* close old console device */
  815. rt_device_close(_console_device);
  816. }
  817. /* set new console device */
  818. _console_device = new;
  819. rt_device_open(_console_device, RT_DEVICE_OFLAG_RDWR);
  820. }
  821. return old;
  822. }
  823. #endif
  824. #if defined(__GNUC__)
  825. void rt_hw_console_output(const char* str) __attribute__((weak));
  826. void rt_hw_console_output(const char* str)
  827. #elif defined(__CC_ARM)
  828. __weak void rt_hw_console_output(const char* str)
  829. #elif defined(__IAR_SYSTEMS_ICC__)
  830. #if __VER__ > 540
  831. __weak
  832. #endif
  833. void rt_hw_console_output(const char* str)
  834. #endif
  835. {
  836. /* empty console output */
  837. }
  838. /**
  839. * This function will print a formatted string on system console
  840. *
  841. * @param fmt the format
  842. */
  843. void rt_kprintf(const char *fmt, ...)
  844. {
  845. va_list args;
  846. rt_size_t length;
  847. static char rt_log_buf[RT_CONSOLEBUF_SIZE];
  848. va_start(args, fmt);
  849. length = vsnprintf(rt_log_buf, sizeof(rt_log_buf), fmt, args);
  850. #ifdef RT_USING_DEVICE
  851. if (_console_device == RT_NULL)
  852. {
  853. rt_hw_console_output(rt_log_buf);
  854. }
  855. else
  856. {
  857. rt_device_write(_console_device, 0, rt_log_buf, length);
  858. }
  859. #else
  860. rt_hw_console_output(rt_log_buf);
  861. #endif
  862. va_end(args);
  863. }
  864. #else
  865. void rt_kprintf(const char *fmt, ...)
  866. {
  867. }
  868. #endif
  869. #if !defined (RT_USING_NEWLIB) && defined (RT_USING_MINILIBC) && defined (__GNUC__)
  870. #include <sys/types.h>
  871. void* memcpy(void *dest, const void *src, size_t n) __attribute__((weak, alias("rt_memcpy")));
  872. void* memset(void *s, int c, size_t n) __attribute__((weak, alias("rt_memset")));
  873. void* memmove(void *dest, const void *src, size_t n) __attribute__((weak, alias("rt_memmove")));
  874. int memcmp(const void *s1, const void *s2, size_t n) __attribute__((weak, alias("rt_memcmp")));
  875. size_t strlen(const char *s) __attribute__((weak, alias("rt_strlen")));
  876. char *strstr(const char *s1,const char *s2) __attribute__((weak, alias("rt_strstr")));
  877. int strcasecmp(const char *a, const char *b) __attribute__((weak, alias("rt_strcasecmp")));
  878. char *strncpy(char *dest, const char *src, size_t n) __attribute__((weak, alias("rt_strncpy")));
  879. int strncmp(const char *cs, const char *ct, size_t count) __attribute__((weak, alias("rt_strncmp")));
  880. #ifdef RT_USING_HEAP
  881. char *strdup(const char *s) __attribute__((weak, alias("rt_strdup")));
  882. #endif
  883. int sprintf(char * buf,const char * format,...) __attribute__((weak, alias("rt_sprintf")));
  884. int snprintf(char *buf, rt_size_t size, const char *fmt, ...) __attribute__((weak, alias("rt_snprintf")));
  885. int vsprintf(char *buf, const char *format, va_list arg_ptr) __attribute__((weak, alias("rt_vsprintf")));
  886. #endif
  887. /*@}*/