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
 |