"Das U-Boot" Source Tree
at master 272 lines 4.9 kB view raw
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 <errno.h> 13#include <malloc.h> 14#include <vsprintf.h> 15#include <linux/ctype.h> 16 17/* from lib/kstrtox.c */ 18static const char *_parse_integer_fixup_radix(const char *s, uint *basep) 19{ 20 /* Look for a 0x prefix */ 21 if (s[0] == '0') { 22 int ch = tolower(s[1]); 23 24 if (ch == 'x') { 25 *basep = 16; 26 s += 2; 27 } else if (!*basep) { 28 /* Only select octal if we don't have a base */ 29 *basep = 8; 30 } 31 } 32 33 /* Use decimal by default */ 34 if (!*basep) 35 *basep = 10; 36 37 return s; 38} 39 40/** 41 * decode_digit() - Decode a single character into its numeric digit value 42 * 43 * This ignore case 44 * 45 * @ch: Character to convert (expects '0'..'9', 'a'..'f' or 'A'..'F') 46 * Return: value of digit (0..0xf) or 255 if the character is invalid 47 */ 48static uint decode_digit(int ch) 49{ 50 if (!isxdigit(ch)) 51 return 256; 52 53 ch = tolower(ch); 54 55 return ch <= '9' ? ch - '0' : ch - 'a' + 0xa; 56} 57 58ulong simple_strtoul(const char *cp, char **endp, uint base) 59{ 60 ulong result = 0; 61 uint value; 62 63 cp = _parse_integer_fixup_radix(cp, &base); 64 65 while (value = decode_digit(*cp), value < base) { 66 result = result * base + value; 67 cp++; 68 } 69 70 if (endp) 71 *endp = (char *)cp; 72 73 return result; 74} 75 76ulong hextoul(const char *cp, char **endp) 77{ 78 return simple_strtoul(cp, endp, 16); 79} 80 81unsigned long long hextoull(const char *cp, char **endp) 82{ 83 return simple_strtoull(cp, endp, 16); 84} 85 86ulong dectoul(const char *cp, char **endp) 87{ 88 return simple_strtoul(cp, endp, 10); 89} 90 91int strict_strtoul(const char *cp, unsigned int base, unsigned long *res) 92{ 93 char *tail; 94 unsigned long val; 95 size_t len; 96 97 *res = 0; 98 len = strlen(cp); 99 if (len == 0) 100 return -EINVAL; 101 102 val = simple_strtoul(cp, &tail, base); 103 if (tail == cp) 104 return -EINVAL; 105 106 if ((*tail == '\0') || 107 ((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) { 108 *res = val; 109 return 0; 110 } 111 112 return -EINVAL; 113} 114 115long simple_strtol(const char *cp, char **endp, unsigned int base) 116{ 117 if (*cp == '-') 118 return -simple_strtoul(cp + 1, endp, base); 119 120 return simple_strtoul(cp, endp, base); 121} 122 123unsigned long ustrtoul(const char *cp, char **endp, unsigned int base) 124{ 125 unsigned long result = simple_strtoul(cp, endp, base); 126 switch (tolower(**endp)) { 127 case 'g': 128 result *= 1024; 129 /* fall through */ 130 case 'm': 131 result *= 1024; 132 /* fall through */ 133 case 'k': 134 result *= 1024; 135 (*endp)++; 136 if (**endp == 'i') 137 (*endp)++; 138 if (**endp == 'B') 139 (*endp)++; 140 } 141 return result; 142} 143 144unsigned long long ustrtoull(const char *cp, char **endp, unsigned int base) 145{ 146 unsigned long long result = simple_strtoull(cp, endp, base); 147 switch (tolower(**endp)) { 148 case 'g': 149 result *= 1024; 150 /* fall through */ 151 case 'm': 152 result *= 1024; 153 /* fall through */ 154 case 'k': 155 result *= 1024; 156 (*endp)++; 157 if (**endp == 'i') 158 (*endp)++; 159 if (**endp == 'B') 160 (*endp)++; 161 } 162 return result; 163} 164 165unsigned long long simple_strtoull(const char *cp, char **endp, 166 unsigned int base) 167{ 168 unsigned long long result = 0; 169 uint value; 170 171 cp = _parse_integer_fixup_radix(cp, &base); 172 173 while (value = decode_digit(*cp), value < base) { 174 result = result * base + value; 175 cp++; 176 } 177 178 if (endp) 179 *endp = (char *) cp; 180 181 return result; 182} 183 184long long simple_strtoll(const char *cp, char **endp, unsigned int base) 185{ 186 if (*cp == '-') 187 return -simple_strtoull(cp + 1, endp, base); 188 189 return simple_strtoull(cp, endp, base); 190} 191 192long trailing_strtoln_end(const char *str, const char *end, char const **endp) 193{ 194 const char *p; 195 196 if (!end) 197 end = str + strlen(str); 198 p = end - 1; 199 if (p > str && isdigit(*p)) { 200 do { 201 if (!isdigit(p[-1])) { 202 if (endp) 203 *endp = p; 204 return dectoul(p, NULL); 205 } 206 } while (--p > str); 207 } 208 if (endp) 209 *endp = end; 210 211 return -1; 212} 213 214long trailing_strtoln(const char *str, const char *end) 215{ 216 return trailing_strtoln_end(str, end, NULL); 217} 218 219long trailing_strtol(const char *str) 220{ 221 return trailing_strtoln(str, NULL); 222} 223 224void str_to_upper(const char *in, char *out, size_t len) 225{ 226 for (; len > 0 && *in; len--) 227 *out++ = toupper(*in++); 228 if (len) 229 *out = '\0'; 230} 231 232const char **str_to_list(const char *instr) 233{ 234 const char **ptr; 235 char *str, *p; 236 int count, i; 237 238 /* don't allocate if the string is empty */ 239 str = *instr ? strdup(instr) : (char *)instr; 240 if (!str) 241 return NULL; 242 243 /* count the number of space-separated strings */ 244 for (count = 0, p = str; *p; p++) { 245 if (*p == ' ') { 246 count++; 247 *p = '\0'; 248 } 249 } 250 if (p != str && p[-1]) 251 count++; 252 253 /* allocate the pointer array, allowing for a NULL terminator */ 254 ptr = calloc(count + 1, sizeof(char *)); 255 if (!ptr) { 256 if (*str) 257 free(str); 258 return NULL; 259 } 260 261 for (i = 0, p = str; i < count; p += strlen(p) + 1, i++) 262 ptr[i] = p; 263 264 return ptr; 265} 266 267void str_free_list(const char **ptr) 268{ 269 if (ptr) 270 free((char *)ptr[0]); 271 free(ptr); 272}