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