170 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			170 lines
		
	
	
		
			3.1 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
 | 
						|
			*base = 10;
 | 
						|
	}
 | 
						|
	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 (**endp) {
 | 
						|
	case 'G':
 | 
						|
		result *= 1024;
 | 
						|
		/* fall through */
 | 
						|
	case 'M':
 | 
						|
		result *= 1024;
 | 
						|
		/* fall through */
 | 
						|
	case 'K':
 | 
						|
	case 'k':
 | 
						|
		result *= 1024;
 | 
						|
		if ((*endp)[1] == 'i') {
 | 
						|
			if ((*endp)[2] == 'B')
 | 
						|
				(*endp) += 3;
 | 
						|
			else
 | 
						|
				(*endp) += 2;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return result;
 | 
						|
}
 | 
						|
 | 
						|
unsigned long long ustrtoull(const char *cp, char **endp, unsigned int base)
 | 
						|
{
 | 
						|
	unsigned long long result = simple_strtoull(cp, endp, base);
 | 
						|
	switch (**endp) {
 | 
						|
	case 'G':
 | 
						|
		result *= 1024;
 | 
						|
		/* fall through */
 | 
						|
	case 'M':
 | 
						|
		result *= 1024;
 | 
						|
		/* fall through */
 | 
						|
	case 'K':
 | 
						|
	case 'k':
 | 
						|
		result *= 1024;
 | 
						|
		if ((*endp)[1] == 'i') {
 | 
						|
			if ((*endp)[2] == 'B')
 | 
						|
				(*endp) += 3;
 | 
						|
			else
 | 
						|
				(*endp) += 2;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	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);
 | 
						|
}
 |