631 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			631 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * Copyright (c) 2006-2018, RT-Thread Development Team
 | |
|  *
 | |
|  * SPDX-License-Identifier: Apache-2.0
 | |
|  *
 | |
|  * Change Logs:
 | |
|  * Date           Author       Notes
 | |
|  * 2008-08-14     Bernard      the first version
 | |
|  * 2010-02-15     Gary Lee     add strlcpy
 | |
|  * 2010-03-17     Bernard      add strlcpy implementation to this file.
 | |
|  *                             fix strlcpy declaration
 | |
|  * 2010-03-24     Bernard      add strchr and strtok implementation.
 | |
|  */
 | |
| 
 | |
| #include <rtthread.h>
 | |
| #include <stdint.h>
 | |
| 
 | |
| #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 (char *)rt_strncpy(dest, src, rt_strlen(src) + 1);
 | |
| }
 | |
| 
 | |
| char *strncpy(char *dest, const char *src, size_t siz)
 | |
| {
 | |
| 	return (char *)rt_strncpy(dest, src, siz);
 | |
| }
 | |
| 
 | |
| size_t strlcpy(char *dst, const char *src, size_t siz)
 | |
| {
 | |
| 	register char *d = dst;
 | |
| 	register const char *s = src;
 | |
| 	register size_t n = siz;
 | |
| 
 | |
| 	/* Copy as many bytes as will fit */
 | |
| 	if (n != 0 && --n != 0)
 | |
| 	{
 | |
| 		do
 | |
| 		{
 | |
| 			if ((*d++ = *s++) == 0) break;
 | |
| 		} while (--n != 0);
 | |
| 	}
 | |
| 
 | |
| 	/* Not enough room in dst, add NUL and traverse rest of src */
 | |
| 	if (n == 0)
 | |
| 	{
 | |
| 		if (siz != 0) *d = '\0';	/* NUL-terminate dst */
 | |
| 		while (*s++) ;
 | |
| 	}
 | |
| 
 | |
| 	return(s - src - 1);			/* count does not include NUL */
 | |
| }
 | |
| 
 | |
| int strcmp (const char *s1, const char *s2)
 | |
| {
 | |
| 	while (*s1 && *s1 == *s2)
 | |
| 		s1++, s2++;
 | |
| 	return (*s1 - *s2);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * strncmp - Compare two length-limited strings
 | |
|  * @cs: One string
 | |
|  * @ct: Another string
 | |
|  * @count: The maximum number of bytes to compare
 | |
|  */
 | |
| int strncmp(const char *cs,const char *ct, size_t count)
 | |
| {
 | |
| 	register signed char __res = 0;
 | |
| 
 | |
| 	while (count) {
 | |
| 		if ((__res = *cs - *ct++) != 0 || !*cs++)
 | |
| 			break;
 | |
| 		count--;
 | |
| 	}
 | |
| 
 | |
| 	return __res;
 | |
| }
 | |
| 
 | |
| char *strcat(char * dest, const char * src)
 | |
| {
 | |
| 	char *tmp = dest;
 | |
| 
 | |
| 	while (*dest)
 | |
| 		dest++;
 | |
| 	while ((*dest++ = *src++) != '\0')
 | |
| 		;
 | |
| 
 | |
| 	return tmp;
 | |
| }
 | |
| 
 | |
| char *strncat(char *dest, const char *src, size_t count)
 | |
| {
 | |
| 	char *tmp = dest;
 | |
| 
 | |
| 	if (count) {
 | |
| 		while (*dest)
 | |
| 			dest++;
 | |
| 		while ((*dest++ = *src++)) {
 | |
| 			if (--count == 0) {
 | |
| 				*dest = '\0';
 | |
| 				break;
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return tmp;
 | |
| }
 | |
| 
 | |
| 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 ((toupper(*cp) == 'X') && isxdigit(cp[1])) {
 | |
| 				cp++;
 | |
| 				base = 16;
 | |
| 			}
 | |
| 		}
 | |
| 	} else if (base == 16) {
 | |
| 		if (cp[0] == '0' && toupper(cp[1]) == 'X')
 | |
| 			cp += 2;
 | |
| 	}
 | |
| 	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 (*cp == '0') {
 | |
| 		cp++;
 | |
| 		if ((toupper(*cp) == 'X') && isxdigit (cp[1])) {
 | |
| 			base = 16;
 | |
| 			cp++;
 | |
| 		}
 | |
| 		if (!base) {
 | |
| 			base = 8;
 | |
| 		}
 | |
| 	}
 | |
| 	if (!base) {
 | |
| 		base = 10;
 | |
| 	}
 | |
| 	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;
 | |
| }
 | |
| 
 | |
| size_t strspn(const char *s, const char *accept)
 | |
| {
 | |
| 	size_t l=0;
 | |
| 	int a=1,i, al=strlen(accept);
 | |
| 
 | |
| 	while((a)&&(*s))
 | |
| 	{
 | |
| 		for(a=i=0;(!a)&&(i<al);i++)
 | |
| 			if (*s==accept[i]) a=1;
 | |
| 		if (a) l++;
 | |
| 		s++;
 | |
| 	}
 | |
| 	return l;
 | |
| }
 | |
| 
 | |
| size_t strcspn(const char *s, const char *reject)
 | |
| {
 | |
| 	size_t l=0;
 | |
| 	int a=1,i,al=strlen(reject);
 | |
| 
 | |
| 	while((a)&&(*s))
 | |
| 	{
 | |
| 		for(i=0;(a)&&(i<al);i++)
 | |
| 			if (*s==reject[i]) a=0;
 | |
| 		if (a) l++;
 | |
| 		s++;
 | |
| 	}
 | |
| 	return l;
 | |
| }
 | |
| 
 | |
| char*strtok_r(char*s,const char*delim,char**ptrptr)
 | |
| {
 | |
| 	char*tmp=0;
 | |
| 
 | |
| 	if (s==0) s=*ptrptr;
 | |
| 	s += strspn(s,delim);	/* overread leading delimiter */
 | |
| 	if (*s)
 | |
| 	{
 | |
| 		tmp=s;
 | |
| 		s+=strcspn(s,delim);
 | |
| 
 | |
| 		if (*s) *s++=0;		/* not the end ? => terminate it */
 | |
| 	}
 | |
| 	*ptrptr=s;
 | |
| 	return tmp;
 | |
| }
 | |
| 
 | |
| char *strtok(char *s, const char *delim)
 | |
| {
 | |
| 	static char *strtok_pos;
 | |
| 	return strtok_r(s,delim,&strtok_pos);
 | |
| }
 | |
| 
 | |
| char *strchr(const char *s1, int i)
 | |
| {
 | |
| 	const unsigned char *s = (const unsigned char *)s1;
 | |
| 	unsigned char c = (unsigned int)i;
 | |
| 
 | |
| 	while (*s && *s != c)
 | |
| 	{
 | |
| 		s++;
 | |
| 	}
 | |
| 
 | |
| 	if (*s != c)
 | |
| 	{
 | |
| 		s = NULL;
 | |
| 	}
 | |
| 
 | |
| 	return (char *) s;
 | |
| }
 | |
| 
 | |
| long strtol(const char *str, char **endptr, int base)
 | |
| {
 | |
|     return simple_strtol(str, endptr, base);
 | |
| }
 | |
| 
 | |
| long long strtoll(const char *str, char **endptr, int base)
 | |
| {
 | |
|     return simple_strtoll(str, endptr, base);
 | |
| }
 | |
| 
 | |
| #endif
 |