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