From 939eaa338f11a259ef4962b6f7ff46c126db0192 Mon Sep 17 00:00:00 2001 From: "bernard.xiong" Date: Sun, 11 Oct 2009 05:44:19 +0000 Subject: [PATCH] add minilibc git-svn-id: https://rt-thread.googlecode.com/svn/trunk@88 bbd45198-f89e-11dd-88c7-29a3b14d5316 --- libc/minilibc/ctype.c | 32 +++ libc/minilibc/ctype.h | 20 ++ libc/minilibc/stddef.h | 4 + libc/minilibc/stdlib.c | 41 ++++ libc/minilibc/stdlib.h | 22 ++ libc/minilibc/string.c | 497 ++++++++++++++++++++++++++++++++++++++ libc/minilibc/string.h | 70 ++++++ libc/minilibc/sys/types.h | 22 ++ 8 files changed, 708 insertions(+) create mode 100644 libc/minilibc/ctype.c create mode 100644 libc/minilibc/ctype.h create mode 100644 libc/minilibc/stddef.h create mode 100644 libc/minilibc/stdlib.c create mode 100644 libc/minilibc/stdlib.h create mode 100644 libc/minilibc/string.c create mode 100644 libc/minilibc/string.h create mode 100644 libc/minilibc/sys/types.h diff --git a/libc/minilibc/ctype.c b/libc/minilibc/ctype.c new file mode 100644 index 0000000000..8e02e1a904 --- /dev/null +++ b/libc/minilibc/ctype.c @@ -0,0 +1,32 @@ +/* + * File : ctype.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2008, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2008-08-14 Bernard the first version + */ + +#include +#include + +#if !defined (RT_USING_NEWLIB) && defined (RT_USING_MINILIBC) +#include "ctype.h" + +int isprint (int ch) +{ + ch&=0x7f; + return (ch>=32 && ch<127); +} + +int isalpha(int ch) +{ + return (unsigned int)((ch | 0x20) - 'a') < 26u; +} + +#endif diff --git a/libc/minilibc/ctype.h b/libc/minilibc/ctype.h new file mode 100644 index 0000000000..fdbf7bf003 --- /dev/null +++ b/libc/minilibc/ctype.h @@ -0,0 +1,20 @@ +/* + * File : ctype.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2008, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2008-08-14 Bernard the first version + */ +#ifndef __CTYPE_H__ +#define __CTYPE_H__ + +int isprint(int c) __attribute__ ((__const__)); +int isalpha (int c) __attribute__ ((__const__)); + +#endif diff --git a/libc/minilibc/stddef.h b/libc/minilibc/stddef.h new file mode 100644 index 0000000000..b260acf79e --- /dev/null +++ b/libc/minilibc/stddef.h @@ -0,0 +1,4 @@ +#ifndef __STDDEF_H__ +#define __STDDEF_H__ + +#endif diff --git a/libc/minilibc/stdlib.c b/libc/minilibc/stdlib.c new file mode 100644 index 0000000000..7c14036351 --- /dev/null +++ b/libc/minilibc/stdlib.c @@ -0,0 +1,41 @@ +/* + * File : stdlib.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2008, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2008-08-14 Bernard the first version + */ + +#include + +#if !defined (RT_USING_NEWLIB) && defined (RT_USING_MINILIBC) +#include "stdlib.h" + +int errno = 0; +int atoi(const char* s) +{ + long int v=0; + int sign=1; + while ( *s == ' ' || (unsigned int)(*s - 9) < 5u) s++; + switch (*s) + { + case '-': + sign=-1; + case '+': + ++s; + } + while ((unsigned int) (*s - '0') < 10u) + { + v=v*10+*s-'0'; + ++s; + } + return sign==-1?-v:v; +} + +#endif diff --git a/libc/minilibc/stdlib.h b/libc/minilibc/stdlib.h new file mode 100644 index 0000000000..c9061a7ab1 --- /dev/null +++ b/libc/minilibc/stdlib.h @@ -0,0 +1,22 @@ +/* + * File : stdlib.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2008, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2008-08-14 Bernard the first version + */ + +#ifndef __STDLIB_H__ +#define __STDLIB_H__ + +#if !defined (RT_USING_NEWLIB) && defined (RT_USING_MINILIBC) +int atoi(const char *nptr); +#endif + +#endif diff --git a/libc/minilibc/string.c b/libc/minilibc/string.c new file mode 100644 index 0000000000..be35afe526 --- /dev/null +++ b/libc/minilibc/string.c @@ -0,0 +1,497 @@ +/* + * File : string.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2008, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2008-08-14 Bernard the first version + */ + +#include + +#if !defined (RT_USING_NEWLIB) && defined (RT_USING_MINILIBC) +#include "string.h" + +/* there is no strcpy and strcmp implementation in RT-Thread */ +char *strcpy(char *dest, const char *src) +{ + return rt_strncpy(dest, src, rt_strlen(src) + 1); +} + +int strcmp (const char *s1, const char *s2) +{ + while (*s1 && *s1 == *s2) + s1++, s2++; + return (*s1 - *s2); +} + +char* strcat(register char* s,register const char* t) +{ + char *dest = s; + + s += strlen(s); + for (;;) + { + if (!(*s = *t)) break; + ++s; + ++t; + } + + return dest; +} + +char *strncat(char *s, const char *t, size_t n) +{ + char *dest = s; + register char *max; + + s += rt_strlen(s); + if ((max=s+n)==s) + goto fini; + for (;;) + { + if (!(*s = *t)) break; + if (++s==max) break; + ++t; + } + *s=0; +fini: + return dest; +} + +char *strrchr(const char *t, int c) +{ + register char ch; + register const char *l=0; + + ch = c; + for (;;) + { + if (*t == ch) l=t; + if (!*t) return (char*)l; + ++t; + } + + return (char*)l; +} + + +int strncasecmp ( const char* s1, const char* s2, size_t len ) +{ + register unsigned int x2; + register unsigned int x1; + register const char* end = s1 + len; + + while (1) + { + if ((s1 >= end) ) + return 0; + + x2 = *s2 - 'A'; if ((x2 < 26u)) x2 += 32; + x1 = *s1 - 'A'; if ((x1 < 26u)) x1 += 32; + s1++; s2++; + + if ((x2 != x1)) + break; + + if ((x1 == (unsigned int)-'A')) + break; + } + + return x1 - x2; +} + +/* private function */ +#define isdigit(c) ((unsigned)((c) - '0') < 10) + +rt_inline int divide(int *n, int base) +{ + rt_int32_t res; + + /* optimized for processor which does not support divide instructions. */ + if (base == 10) + { + res = ((int)*n) % 10U; + *n = ((int)*n) / 10U; + } + else + { + res = ((int)*n) % 16U; + *n = ((int)*n) / 16U; + } + + return res; +} + +rt_inline int skip_atoi(const char **s) +{ + register int i=0; + while (isdigit(**s)) i = i*10 + *((*s)++) - '0'; + + return i; +} + +unsigned char _ctype[] = { +_C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */ +_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */ +_C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */ +_C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */ +_S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */ +_P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */ +_D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */ +_D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */ +_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */ +_U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */ +_U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */ +_U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */ +_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */ +_L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */ +_L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */ +_L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */ +_S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */ +_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */ +_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */ +_U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */ +_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */ +_L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */ + +#define __ismask(x) (_ctype[(int)(unsigned char)(x)]) + +#define isalnum(c) ((__ismask(c)&(_U|_L|_D)) != 0) +#define isalpha(c) ((__ismask(c)&(_U|_L)) != 0) +#define iscntrl(c) ((__ismask(c)&(_C)) != 0) +#define isgraph(c) ((__ismask(c)&(_P|_U|_L|_D)) != 0) +#define islower(c) ((__ismask(c)&(_L)) != 0) +#define isprint(c) ((__ismask(c)&(_P|_U|_L|_D|_SP)) != 0) +#define ispunct(c) ((__ismask(c)&(_P)) != 0) +#define isspace(c) ((__ismask(c)&(_S)) != 0) +#define isupper(c) ((__ismask(c)&(_U)) != 0) +#define isxdigit(c) ((__ismask(c)&(_D|_X)) != 0) + +#define isascii(c) (((unsigned char)(c))<=0x7f) +#define toascii(c) (((unsigned char)(c))&0x7f) + +static inline unsigned char __tolower(unsigned char c) +{ + if (isupper(c)) + c -= 'A'-'a'; + return c; +} + +static inline unsigned char __toupper(unsigned char c) +{ + if (islower(c)) + c -= 'a'-'A'; + return c; +} + +int tolower(int c) +{ + return __tolower(c); +} + +int toupper(int c) +{ + return __toupper(c); +} + +/** + * simple_strtoul - convert a string to an unsigned long + * @cp: The start of the string + * @endp: A pointer to the end of the parsed string will be placed here + * @base: The number base to use + */ +unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base) +{ + unsigned long result = 0,value; + + if (!base) { + base = 10; + if (*cp == '0') { + base = 8; + cp++; + if ((*cp == 'x') && isxdigit(cp[1])) { + cp++; + base = 16; + } + } + } + while (isxdigit(*cp) && + (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) { + result = result*base + value; + cp++; + } + if (endp) + *endp = (char *)cp; + return result; +} + +/** + * simple_strtol - convert a string to a signed long + * @cp: The start of the string + * @endp: A pointer to the end of the parsed string will be placed here + * @base: The number base to use + */ +long simple_strtol(const char *cp,char **endp,unsigned int base) +{ + if(*cp=='-') + return -simple_strtoul(cp+1,endp,base); + return simple_strtoul(cp,endp,base); +} + +/** + * simple_strtoull - convert a string to an unsigned long long + * @cp: The start of the string + * @endp: A pointer to the end of the parsed string will be placed here + * @base: The number base to use + */ +unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int base) +{ + unsigned long long result = 0,value; + + if (!base) { + base = 10; + if (*cp == '0') { + base = 8; + cp++; + if ((*cp == 'x') && isxdigit(cp[1])) { + cp++; + base = 16; + } + } + } + while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp) + ? toupper(*cp) : *cp)-'A'+10) < base) { + result = result*base + value; + cp++; + } + if (endp) + *endp = (char *)cp; + return result; +} + +/** + * simple_strtoll - convert a string to a signed long long + * @cp: The start of the string + * @endp: A pointer to the end of the parsed string will be placed here + * @base: The number base to use + */ +long long simple_strtoll(const char *cp,char **endp,unsigned int base) +{ + if(*cp=='-') + return -simple_strtoull(cp+1,endp,base); + return simple_strtoull(cp,endp,base); +} + +/** + * vsscanf - Unformat a buffer into a list of arguments + * @buf: input buffer + * @fmt: format of buffer + * @args: arguments + */ +int vsscanf(const char * buf, const char * fmt, va_list args) +{ + const char *str = buf; + char *next; + int num = 0; + int qualifier; + int base; + int field_width = -1; + int is_sign = 0; + + while(*fmt && *str) { + /* skip any white space in format */ + /* white space in format matchs any amount of + * white space, including none, in the input. + */ + if (isspace(*fmt)) { + while (isspace(*fmt)) + ++fmt; + while (isspace(*str)) + ++str; + } + + /* anything that is not a conversion must match exactly */ + if (*fmt != '%' && *fmt) { + if (*fmt++ != *str++) + break; + continue; + } + + if (!*fmt) + break; + ++fmt; + + /* skip this conversion. + * advance both strings to next white space + */ + if (*fmt == '*') { + while (!isspace(*fmt) && *fmt) + fmt++; + while (!isspace(*str) && *str) + str++; + continue; + } + + /* get field width */ + if (isdigit(*fmt)) + field_width = skip_atoi(&fmt); + + /* get conversion qualifier */ + qualifier = -1; + if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt == 'Z') { + qualifier = *fmt; + fmt++; + } + base = 10; + is_sign = 0; + + if (!*fmt || !*str) + break; + + switch(*fmt++) { + case 'c': + { + char *s = (char *) va_arg(args,char*); + if (field_width == -1) + field_width = 1; + do { + *s++ = *str++; + } while(field_width-- > 0 && *str); + num++; + } + continue; + case 's': + { + char *s = (char *) va_arg(args, char *); + if(field_width == -1) + field_width = INT_MAX; + /* first, skip leading white space in buffer */ + while (isspace(*str)) + str++; + + /* now copy until next white space */ + while (*str && !isspace(*str) && field_width--) { + *s++ = *str++; + } + *s = '\0'; + num++; + } + continue; + case 'n': + /* return number of characters read so far */ + { + int *i = (int *)va_arg(args,int*); + *i = str - buf; + } + continue; + case 'o': + base = 8; + break; + case 'x': + case 'X': + base = 16; + break; + case 'd': + case 'i': + is_sign = 1; + case 'u': + break; + case '%': + /* looking for '%' in str */ + if (*str++ != '%') + return num; + continue; + default: + /* invalid format; stop here */ + return num; + } + + /* have some sort of integer conversion. + * first, skip white space in buffer. + */ + while (isspace(*str)) + str++; + + if (!*str || !isdigit(*str)) + break; + + switch(qualifier) { + case 'h': + if (is_sign) { + short *s = (short *) va_arg(args,short *); + *s = (short) simple_strtol(str,&next,base); + } else { + unsigned short *s = (unsigned short *) va_arg(args, unsigned short *); + *s = (unsigned short) simple_strtoul(str, &next, base); + } + break; + case 'l': + if (is_sign) { + long *l = (long *) va_arg(args,long *); + *l = simple_strtol(str,&next,base); + } else { + unsigned long *l = (unsigned long*) va_arg(args,unsigned long*); + *l = simple_strtoul(str,&next,base); + } + break; + case 'L': + if (is_sign) { + long long *l = (long long*) va_arg(args,long long *); + *l = simple_strtoll(str,&next,base); + } else { + unsigned long long *l = (unsigned long long*) va_arg(args,unsigned long long*); + *l = simple_strtoull(str,&next,base); + } + break; + case 'Z': + { + unsigned long *s = (unsigned long*) va_arg(args,unsigned long*); + *s = (unsigned long) simple_strtoul(str,&next,base); + } + break; + default: + if (is_sign) { + int *i = (int *) va_arg(args, int*); + *i = (int) simple_strtol(str,&next,base); + } else { + unsigned int *i = (unsigned int*) va_arg(args, unsigned int*); + *i = (unsigned int) simple_strtoul(str,&next,base); + } + break; + } + num++; + + if (!next) + break; + str = next; + } + return num; +} + +/** + * sscanf - Unformat a buffer into a list of arguments + * @buf: input buffer + * @fmt: formatting of buffer + * @...: resulting arguments + */ +int sscanf(const char * buf, const char * fmt, ...) +{ + va_list args; + int i; + + va_start(args,fmt); + i = vsscanf(buf,fmt,args); + va_end(args); + + return i; +} + +#endif diff --git a/libc/minilibc/string.h b/libc/minilibc/string.h new file mode 100644 index 0000000000..2435334170 --- /dev/null +++ b/libc/minilibc/string.h @@ -0,0 +1,70 @@ +/* + * File : string.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2008, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2008-08-14 Bernard the first version + */ +#ifndef __STRING_H__ +#define __STRING_H__ + +#include +#include + +/* replace for standard string library */ +#if !defined (RT_USING_NEWLIB) && defined (RT_USING_MINILIBC) + +#define ZEROPAD (1 << 0) /* pad with zero */ +#define SIGN (1 << 1) /* unsigned/signed long */ +#define PLUS (1 << 2) /* show plus */ +#define SPACE (1 << 3) /* space if plus */ +#define LEFT (1 << 4) /* left justified */ +#define SPECIAL (1 << 5) /* 0x */ +#define LARGE (1 << 6) /* use 'ABCDEF' instead of 'abcdef' */ + +#define INT_MAX ((int)(~0U>>1)) +#define INT_MIN (-INT_MAX - 1) +#define UINT_MAX (~0U) +#define LONG_MAX ((long)(~0UL>>1)) +#define LONG_MIN (-LONG_MAX - 1) +#define ULONG_MAX (~0UL) + +#define _U 0x01 /* upper */ +#define _L 0x02 /* lower */ +#define _D 0x04 /* digit */ +#define _C 0x08 /* cntrl */ +#define _P 0x10 /* punct */ +#define _S 0x20 /* white space (space/lf/tab) */ +#define _X 0x40 /* hex digit */ +#define _SP 0x80 /* hard space (0x20) */ + +void* memset(void *s, int c, size_t n); +void* memcpy(void *dest, const void *src, size_t n); +void* memmove(void *dest, const void *src, size_t n); +int memcmp(const void *s1, const void *s2, size_t n); + +int tolower(int c); +int toupper(int c); + +int strcmp (const char *s1, const char *s2); +int strcasecmp(const char *a, const char *b); +int strncasecmp(const char *cs, const char *ct, size_t count); +int sscanf(const char * buf, const char * fmt, ...); +size_t strlen(const char *s); +char * strstr(const char * s1,const char * s2); +char *strcpy(char *dest, const char *src); +char *strncpy(char *dest, const char *src, size_t n); +char *strncat(char *s, const char *t, size_t n) ; +char* strcat(register char* s,register const char* t); +char *strrchr(const char *t, int c); +char *strdup(const char *s); + +#endif + +#endif diff --git a/libc/minilibc/sys/types.h b/libc/minilibc/sys/types.h new file mode 100644 index 0000000000..035250c076 --- /dev/null +++ b/libc/minilibc/sys/types.h @@ -0,0 +1,22 @@ +#ifndef __TYPES_H__ +#define __TYPES_H__ + +#include + +typedef rt_off_t off_t; +typedef rt_size_t size_t; + +typedef rt_uint8_t u_char; +typedef rt_uint16_t u_short; +typedef rt_ubase_t u_int; +typedef rt_uint32_t u_long; + +typedef rt_uint8_t u_int8_t; +typedef rt_uint16_t u_int16_t; +typedef rt_uint32_t u_int32_t; + +#ifndef NULL +#define NULL RT_NULL +#endif + +#endif