1*8ccd4a63SDavid du Colombier #include <u.h> 2*8ccd4a63SDavid du Colombier #include <libc.h> 3*8ccd4a63SDavid du Colombier #define VLONG_MAX ~(((vlong) 1)<<63) 4*8ccd4a63SDavid du Colombier #define VLONG_MIN (((vlong) 1)<<63) 5*8ccd4a63SDavid du Colombier vlong 6*8ccd4a63SDavid du Colombier strtoll(const char *nptr, char **endptr, int base) 7*8ccd4a63SDavid du Colombier { 8*8ccd4a63SDavid du Colombier char *p; 9*8ccd4a63SDavid du Colombier vlong n, nn, m; 10*8ccd4a63SDavid du Colombier int c, ovfl, v, neg, ndig; 11*8ccd4a63SDavid du Colombier p = (char*)nptr; 12*8ccd4a63SDavid du Colombier neg = 0; 13*8ccd4a63SDavid du Colombier n = 0; 14*8ccd4a63SDavid du Colombier ndig = 0; 15*8ccd4a63SDavid du Colombier ovfl = 0; 16*8ccd4a63SDavid du Colombier /* 17*8ccd4a63SDavid du Colombier * White space 18*8ccd4a63SDavid du Colombier */ 19*8ccd4a63SDavid du Colombier for(;; p++) { 20*8ccd4a63SDavid du Colombier switch(*p) { 21*8ccd4a63SDavid du Colombier case ' ': 22*8ccd4a63SDavid du Colombier case '\t': 23*8ccd4a63SDavid du Colombier case '\n': 24*8ccd4a63SDavid du Colombier case '\f': 25*8ccd4a63SDavid du Colombier case '\r': 26*8ccd4a63SDavid du Colombier case '\v': 27*8ccd4a63SDavid du Colombier continue; 28*8ccd4a63SDavid du Colombier } 29*8ccd4a63SDavid du Colombier break; 30*8ccd4a63SDavid du Colombier } 31*8ccd4a63SDavid du Colombier /* 32*8ccd4a63SDavid du Colombier * Sign 33*8ccd4a63SDavid du Colombier */ 34*8ccd4a63SDavid du Colombier if(*p=='-' || *p=='+') 35*8ccd4a63SDavid du Colombier if(*p++ == '-') 36*8ccd4a63SDavid du Colombier neg = 1; 37*8ccd4a63SDavid du Colombier /* 38*8ccd4a63SDavid du Colombier * Base 39*8ccd4a63SDavid du Colombier */ 40*8ccd4a63SDavid du Colombier if(base==0){ 41*8ccd4a63SDavid du Colombier base = 10; 42*8ccd4a63SDavid du Colombier if(*p == '0') { 43*8ccd4a63SDavid du Colombier base = 8; 44*8ccd4a63SDavid du Colombier if(p[1]=='x' || p[1]=='X') { 45*8ccd4a63SDavid du Colombier p += 2; 46*8ccd4a63SDavid du Colombier base = 16; 47*8ccd4a63SDavid du Colombier } 48*8ccd4a63SDavid du Colombier } 49*8ccd4a63SDavid du Colombier } else 50*8ccd4a63SDavid du Colombier if(base==16 && *p=='0') { 51*8ccd4a63SDavid du Colombier if(p[1]=='x' || p[1]=='X') 52*8ccd4a63SDavid du Colombier p += 2; 53*8ccd4a63SDavid du Colombier } else 54*8ccd4a63SDavid du Colombier if(base<0 || 36<base) 55*8ccd4a63SDavid du Colombier goto Return; 56*8ccd4a63SDavid du Colombier /* 57*8ccd4a63SDavid du Colombier * Non-empty sequence of digits 58*8ccd4a63SDavid du Colombier */ 59*8ccd4a63SDavid du Colombier m = VLONG_MAX/base; 60*8ccd4a63SDavid du Colombier for(;; p++,ndig++) { 61*8ccd4a63SDavid du Colombier c = *p; 62*8ccd4a63SDavid du Colombier v = base; 63*8ccd4a63SDavid du Colombier if('0'<=c && c<='9') 64*8ccd4a63SDavid du Colombier v = c - '0'; 65*8ccd4a63SDavid du Colombier else 66*8ccd4a63SDavid du Colombier if('a'<=c && c<='z') 67*8ccd4a63SDavid du Colombier v = c - 'a' + 10; 68*8ccd4a63SDavid du Colombier else 69*8ccd4a63SDavid du Colombier if('A'<=c && c<='Z') 70*8ccd4a63SDavid du Colombier v = c - 'A' + 10; 71*8ccd4a63SDavid du Colombier if(v >= base) 72*8ccd4a63SDavid du Colombier break; 73*8ccd4a63SDavid du Colombier if(n > m) 74*8ccd4a63SDavid du Colombier ovfl = 1; 75*8ccd4a63SDavid du Colombier nn = n*base + v; 76*8ccd4a63SDavid du Colombier if(nn < n) 77*8ccd4a63SDavid du Colombier ovfl = 1; 78*8ccd4a63SDavid du Colombier n = nn; 79*8ccd4a63SDavid du Colombier } 80*8ccd4a63SDavid du Colombier Return: 81*8ccd4a63SDavid du Colombier if(ndig == 0) 82*8ccd4a63SDavid du Colombier p = (char*)nptr; 83*8ccd4a63SDavid du Colombier if(endptr) 84*8ccd4a63SDavid du Colombier *endptr = p; 85*8ccd4a63SDavid du Colombier if(ovfl){ 86*8ccd4a63SDavid du Colombier if(neg) 87*8ccd4a63SDavid du Colombier return VLONG_MIN; 88*8ccd4a63SDavid du Colombier return VLONG_MAX; 89*8ccd4a63SDavid du Colombier } 90*8ccd4a63SDavid du Colombier if(neg) 91*8ccd4a63SDavid du Colombier return -n; 92*8ccd4a63SDavid du Colombier return n; 93*8ccd4a63SDavid du Colombier } 94