mirror of
				https://xff.cz/git/u-boot/
				synced 2025-10-31 18:35:42 +01:00 
			
		
		
		
	At present it is not possible to find out which part of the string is the number part and which is before it. Add a new variant which provides this feature, so we can separate the two in the caller. Signed-off-by: Simon Glass <sjg@chromium.org>
		
			
				
	
	
		
			225 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			225 lines
		
	
	
		
			4.0 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, uint *basep)
 | |
| {
 | |
| 	/* Look for a 0x prefix */
 | |
| 	if (s[0] == '0') {
 | |
| 		int ch = tolower(s[1]);
 | |
| 
 | |
| 		if (ch == 'x') {
 | |
| 			*basep = 16;
 | |
| 			s += 2;
 | |
| 		} else if (!*basep) {
 | |
| 			/* Only select octal if we don't have a base */
 | |
| 			*basep = 8;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/* Use decimal by default */
 | |
| 	if (!*basep)
 | |
| 		*basep = 10;
 | |
| 
 | |
| 	return s;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * decode_digit() - Decode a single character into its numeric digit value
 | |
|  *
 | |
|  * This ignore case
 | |
|  *
 | |
|  * @ch: Character to convert (expects '0'..'9', 'a'..'f' or 'A'..'F')
 | |
|  * Return: value of digit (0..0xf) or 255 if the character is invalid
 | |
|  */
 | |
| static uint decode_digit(int ch)
 | |
| {
 | |
| 	if (!isxdigit(ch))
 | |
| 		return 256;
 | |
| 
 | |
| 	ch = tolower(ch);
 | |
| 
 | |
| 	return ch <= '9' ? ch - '0' : ch - 'a' + 0xa;
 | |
| }
 | |
| 
 | |
| ulong simple_strtoul(const char *cp, char **endp, uint base)
 | |
| {
 | |
| 	ulong result = 0;
 | |
| 	uint value;
 | |
| 
 | |
| 	cp = _parse_integer_fixup_radix(cp, &base);
 | |
| 
 | |
| 	while (value = decode_digit(*cp), value < base) {
 | |
| 		result = result * base + value;
 | |
| 		cp++;
 | |
| 	}
 | |
| 
 | |
| 	if (endp)
 | |
| 		*endp = (char *)cp;
 | |
| 
 | |
| 	return result;
 | |
| }
 | |
| 
 | |
| ulong hextoul(const char *cp, char **endp)
 | |
| {
 | |
| 	return simple_strtoul(cp, endp, 16);
 | |
| }
 | |
| 
 | |
| ulong dectoul(const char *cp, char **endp)
 | |
| {
 | |
| 	return simple_strtoul(cp, endp, 10);
 | |
| }
 | |
| 
 | |
| 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;
 | |
| 	uint value;
 | |
| 
 | |
| 	cp = _parse_integer_fixup_radix(cp, &base);
 | |
| 
 | |
| 	while (value = decode_digit(*cp), value < base) {
 | |
| 		result = result * base + value;
 | |
| 		cp++;
 | |
| 	}
 | |
| 
 | |
| 	if (endp)
 | |
| 		*endp = (char *) cp;
 | |
| 
 | |
| 	return result;
 | |
| }
 | |
| 
 | |
| 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);
 | |
| }
 | |
| 
 | |
| long trailing_strtoln_end(const char *str, const char *end, char const **endp)
 | |
| {
 | |
| 	const char *p;
 | |
| 
 | |
| 	if (!end)
 | |
| 		end = str + strlen(str);
 | |
| 	p = end - 1;
 | |
| 	if (p > str && isdigit(*p)) {
 | |
| 		do {
 | |
| 			if (!isdigit(p[-1])) {
 | |
| 				if (endp)
 | |
| 					*endp = p;
 | |
| 				return dectoul(p, NULL);
 | |
| 			}
 | |
| 		} while (--p > str);
 | |
| 	}
 | |
| 	if (endp)
 | |
| 		*endp = end;
 | |
| 
 | |
| 	return -1;
 | |
| }
 | |
| 
 | |
| long trailing_strtoln(const char *str, const char *end)
 | |
| {
 | |
| 	return trailing_strtoln_end(str, end, NULL);
 | |
| }
 | |
| 
 | |
| 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';
 | |
| }
 |