190 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			190 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			C
		
	
	
	
| /*
 | |
|  *  linux/lib/vsprintf.c
 | |
|  *
 | |
|  *  Copyright (C) 1991, 1992  Linus Torvalds
 | |
|  */
 | |
| 
 | |
| /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
 | |
| /*
 | |
|  * Wirzenius wrote this portably, Torvalds fucked it up :-)
 | |
|  */
 | |
| 
 | |
| #include <common.h>
 | |
| #include <errno.h>
 | |
| #include <linux/ctype.h>
 | |
| 
 | |
| /* from lib/kstrtox.c */
 | |
| static const char *_parse_integer_fixup_radix(const char *s, unsigned int *base)
 | |
| {
 | |
| 	if (*base == 0) {
 | |
| 		if (s[0] == '0') {
 | |
| 			if (tolower(s[1]) == 'x' && isxdigit(s[2]))
 | |
| 				*base = 16;
 | |
| 			else
 | |
| 				*base = 8;
 | |
| 		} else {
 | |
| 			int i = 0;
 | |
| 			char var;
 | |
| 
 | |
| 			*base = 10;
 | |
| 
 | |
| 			do {
 | |
| 				var = tolower(s[i++]);
 | |
| 				if (var >= 'a' && var <= 'f') {
 | |
| 					*base = 16;
 | |
| 					break;
 | |
| 				}
 | |
| 
 | |
| 				if (!(var >= '0' && var <= '9'))
 | |
| 					break;
 | |
| 			} while (var);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if (*base == 16 && s[0] == '0' && tolower(s[1]) == 'x')
 | |
| 		s += 2;
 | |
| 	return s;
 | |
| }
 | |
| 
 | |
| unsigned long simple_strtoul(const char *cp, char **endp,
 | |
| 				unsigned int base)
 | |
| {
 | |
| 	unsigned long result = 0;
 | |
| 	unsigned long value;
 | |
| 
 | |
| 	cp = _parse_integer_fixup_radix(cp, &base);
 | |
| 
 | |
| 	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;
 | |
| }
 | |
| 
 | |
| int strict_strtoul(const char *cp, unsigned int base, unsigned long *res)
 | |
| {
 | |
| 	char *tail;
 | |
| 	unsigned long val;
 | |
| 	size_t len;
 | |
| 
 | |
| 	*res = 0;
 | |
| 	len = strlen(cp);
 | |
| 	if (len == 0)
 | |
| 		return -EINVAL;
 | |
| 
 | |
| 	val = simple_strtoul(cp, &tail, base);
 | |
| 	if (tail == cp)
 | |
| 		return -EINVAL;
 | |
| 
 | |
| 	if ((*tail == '\0') ||
 | |
| 		((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) {
 | |
| 		*res = val;
 | |
| 		return 0;
 | |
| 	}
 | |
| 
 | |
| 	return -EINVAL;
 | |
| }
 | |
| 
 | |
| 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);
 | |
| }
 | |
| 
 | |
| unsigned long ustrtoul(const char *cp, char **endp, unsigned int base)
 | |
| {
 | |
| 	unsigned long result = simple_strtoul(cp, endp, base);
 | |
| 	switch (tolower(**endp)) {
 | |
| 	case 'g':
 | |
| 		result *= 1024;
 | |
| 		/* fall through */
 | |
| 	case 'm':
 | |
| 		result *= 1024;
 | |
| 		/* fall through */
 | |
| 	case 'k':
 | |
| 		result *= 1024;
 | |
| 		(*endp)++;
 | |
| 		if (**endp == 'i')
 | |
| 			(*endp)++;
 | |
| 		if (**endp == 'B')
 | |
| 			(*endp)++;
 | |
| 	}
 | |
| 	return result;
 | |
| }
 | |
| 
 | |
| unsigned long long ustrtoull(const char *cp, char **endp, unsigned int base)
 | |
| {
 | |
| 	unsigned long long result = simple_strtoull(cp, endp, base);
 | |
| 	switch (tolower(**endp)) {
 | |
| 	case 'g':
 | |
| 		result *= 1024;
 | |
| 		/* fall through */
 | |
| 	case 'm':
 | |
| 		result *= 1024;
 | |
| 		/* fall through */
 | |
| 	case 'k':
 | |
| 		result *= 1024;
 | |
| 		(*endp)++;
 | |
| 		if (**endp == 'i')
 | |
| 			(*endp)++;
 | |
| 		if (**endp == 'B')
 | |
| 			(*endp)++;
 | |
| 	}
 | |
| 	return result;
 | |
| }
 | |
| 
 | |
| unsigned long long simple_strtoull(const char *cp, char **endp,
 | |
| 					unsigned int base)
 | |
| {
 | |
| 	unsigned long long result = 0, value;
 | |
| 
 | |
| 	cp = _parse_integer_fixup_radix(cp, &base);
 | |
| 
 | |
| 	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;
 | |
| }
 | |
| 
 | |
| long trailing_strtoln(const char *str, const char *end)
 | |
| {
 | |
| 	const char *p;
 | |
| 
 | |
| 	if (!end)
 | |
| 		end = str + strlen(str);
 | |
| 	if (isdigit(end[-1])) {
 | |
| 		for (p = end - 1; p > str; p--) {
 | |
| 			if (!isdigit(*p))
 | |
| 				return simple_strtoul(p + 1, NULL, 10);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return -1;
 | |
| }
 | |
| 
 | |
| long trailing_strtol(const char *str)
 | |
| {
 | |
| 	return trailing_strtoln(str, NULL);
 | |
| }
 | |
| 
 | |
| void str_to_upper(const char *in, char *out, size_t len)
 | |
| {
 | |
| 	for (; len > 0 && *in; len--)
 | |
| 		*out++ = toupper(*in++);
 | |
| 	if (len)
 | |
| 		*out = '\0';
 | |
| }
 |