Home | History | Annotate | Download | only in lib
      1 /*
      2  *  linux/lib/vsprintf.c
      3  *
      4  *  Copyright (C) 1991, 1992  Linus Torvalds
      5  */
      6 
      7 /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
      8 /*
      9  * Wirzenius wrote this portably, Torvalds fucked it up :-)
     10  */
     11 
     12 #include <common.h>
     13 #include <errno.h>
     14 #include <linux/ctype.h>
     15 
     16 /* from lib/kstrtox.c */
     17 static const char *_parse_integer_fixup_radix(const char *s, unsigned int *base)
     18 {
     19 	if (*base == 0) {
     20 		if (s[0] == '0') {
     21 			if (tolower(s[1]) == 'x' && isxdigit(s[2]))
     22 				*base = 16;
     23 			else
     24 				*base = 8;
     25 		} else
     26 			*base = 10;
     27 	}
     28 	if (*base == 16 && s[0] == '0' && tolower(s[1]) == 'x')
     29 		s += 2;
     30 	return s;
     31 }
     32 
     33 unsigned long simple_strtoul(const char *cp, char **endp,
     34 				unsigned int base)
     35 {
     36 	unsigned long result = 0;
     37 	unsigned long value;
     38 
     39 	cp = _parse_integer_fixup_radix(cp, &base);
     40 
     41 	while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
     42 	    ? toupper(*cp) : *cp)-'A'+10) < base) {
     43 		result = result*base + value;
     44 		cp++;
     45 	}
     46 
     47 	if (endp)
     48 		*endp = (char *)cp;
     49 
     50 	return result;
     51 }
     52 
     53 int strict_strtoul(const char *cp, unsigned int base, unsigned long *res)
     54 {
     55 	char *tail;
     56 	unsigned long val;
     57 	size_t len;
     58 
     59 	*res = 0;
     60 	len = strlen(cp);
     61 	if (len == 0)
     62 		return -EINVAL;
     63 
     64 	val = simple_strtoul(cp, &tail, base);
     65 	if (tail == cp)
     66 		return -EINVAL;
     67 
     68 	if ((*tail == '\0') ||
     69 		((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) {
     70 		*res = val;
     71 		return 0;
     72 	}
     73 
     74 	return -EINVAL;
     75 }
     76 
     77 long simple_strtol(const char *cp, char **endp, unsigned int base)
     78 {
     79 	if (*cp == '-')
     80 		return -simple_strtoul(cp + 1, endp, base);
     81 
     82 	return simple_strtoul(cp, endp, base);
     83 }
     84 
     85 unsigned long ustrtoul(const char *cp, char **endp, unsigned int base)
     86 {
     87 	unsigned long result = simple_strtoul(cp, endp, base);
     88 	switch (**endp) {
     89 	case 'G':
     90 		result *= 1024;
     91 		/* fall through */
     92 	case 'M':
     93 		result *= 1024;
     94 		/* fall through */
     95 	case 'K':
     96 	case 'k':
     97 		result *= 1024;
     98 		if ((*endp)[1] == 'i') {
     99 			if ((*endp)[2] == 'B')
    100 				(*endp) += 3;
    101 			else
    102 				(*endp) += 2;
    103 		}
    104 	}
    105 	return result;
    106 }
    107 
    108 unsigned long long ustrtoull(const char *cp, char **endp, unsigned int base)
    109 {
    110 	unsigned long long result = simple_strtoull(cp, endp, base);
    111 	switch (**endp) {
    112 	case 'G':
    113 		result *= 1024;
    114 		/* fall through */
    115 	case 'M':
    116 		result *= 1024;
    117 		/* fall through */
    118 	case 'K':
    119 	case 'k':
    120 		result *= 1024;
    121 		if ((*endp)[1] == 'i') {
    122 			if ((*endp)[2] == 'B')
    123 				(*endp) += 3;
    124 			else
    125 				(*endp) += 2;
    126 		}
    127 	}
    128 	return result;
    129 }
    130 
    131 unsigned long long simple_strtoull(const char *cp, char **endp,
    132 					unsigned int base)
    133 {
    134 	unsigned long long result = 0, value;
    135 
    136 	cp = _parse_integer_fixup_radix(cp, &base);
    137 
    138 	while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp - '0'
    139 		: (islower(*cp) ? toupper(*cp) : *cp) - 'A' + 10) < base) {
    140 		result = result * base + value;
    141 		cp++;
    142 	}
    143 
    144 	if (endp)
    145 		*endp = (char *) cp;
    146 
    147 	return result;
    148 }
    149 
    150 long trailing_strtoln(const char *str, const char *end)
    151 {
    152 	const char *p;
    153 
    154 	if (!end)
    155 		end = str + strlen(str);
    156 	if (isdigit(end[-1])) {
    157 		for (p = end - 1; p > str; p--) {
    158 			if (!isdigit(*p))
    159 				return simple_strtoul(p + 1, NULL, 10);
    160 		}
    161 	}
    162 
    163 	return -1;
    164 }
    165 
    166 long trailing_strtol(const char *str)
    167 {
    168 	return trailing_strtoln(str, NULL);
    169 }
    170