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