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