kservice.c 20 KB

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