18ccd4a63SDavid du Colombier #include <u.h>
28ccd4a63SDavid du Colombier #include <libc.h>
3*ec59a3ddSDavid du Colombier #define VLONG_MAX ((vlong)~(((uvlong)1)<<63))
4*ec59a3ddSDavid du Colombier #define VLONG_MIN ((vlong)(((uvlong)1)<<63))
58ccd4a63SDavid du Colombier vlong
strtoll(const char * nptr,char ** endptr,int base)68ccd4a63SDavid du Colombier strtoll(const char *nptr, char **endptr, int base)
78ccd4a63SDavid du Colombier {
88ccd4a63SDavid du Colombier char *p;
98ccd4a63SDavid du Colombier vlong n, nn, m;
108ccd4a63SDavid du Colombier int c, ovfl, v, neg, ndig;
118ccd4a63SDavid du Colombier p = (char*)nptr;
128ccd4a63SDavid du Colombier neg = 0;
138ccd4a63SDavid du Colombier n = 0;
148ccd4a63SDavid du Colombier ndig = 0;
158ccd4a63SDavid du Colombier ovfl = 0;
168ccd4a63SDavid du Colombier /*
178ccd4a63SDavid du Colombier * White space
188ccd4a63SDavid du Colombier */
198ccd4a63SDavid du Colombier for(;; p++) {
208ccd4a63SDavid du Colombier switch(*p) {
218ccd4a63SDavid du Colombier case ' ':
228ccd4a63SDavid du Colombier case '\t':
238ccd4a63SDavid du Colombier case '\n':
248ccd4a63SDavid du Colombier case '\f':
258ccd4a63SDavid du Colombier case '\r':
268ccd4a63SDavid du Colombier case '\v':
278ccd4a63SDavid du Colombier continue;
288ccd4a63SDavid du Colombier }
298ccd4a63SDavid du Colombier break;
308ccd4a63SDavid du Colombier }
318ccd4a63SDavid du Colombier /*
328ccd4a63SDavid du Colombier * Sign
338ccd4a63SDavid du Colombier */
348ccd4a63SDavid du Colombier if(*p=='-' || *p=='+')
358ccd4a63SDavid du Colombier if(*p++ == '-')
368ccd4a63SDavid du Colombier neg = 1;
378ccd4a63SDavid du Colombier /*
388ccd4a63SDavid du Colombier * Base
398ccd4a63SDavid du Colombier */
408ccd4a63SDavid du Colombier if(base==0){
418ccd4a63SDavid du Colombier base = 10;
428ccd4a63SDavid du Colombier if(*p == '0') {
438ccd4a63SDavid du Colombier base = 8;
448ccd4a63SDavid du Colombier if(p[1]=='x' || p[1]=='X') {
458ccd4a63SDavid du Colombier p += 2;
468ccd4a63SDavid du Colombier base = 16;
478ccd4a63SDavid du Colombier }
488ccd4a63SDavid du Colombier }
498ccd4a63SDavid du Colombier } else
508ccd4a63SDavid du Colombier if(base==16 && *p=='0') {
518ccd4a63SDavid du Colombier if(p[1]=='x' || p[1]=='X')
528ccd4a63SDavid du Colombier p += 2;
538ccd4a63SDavid du Colombier } else
548ccd4a63SDavid du Colombier if(base<0 || 36<base)
558ccd4a63SDavid du Colombier goto Return;
568ccd4a63SDavid du Colombier /*
578ccd4a63SDavid du Colombier * Non-empty sequence of digits
588ccd4a63SDavid du Colombier */
598ccd4a63SDavid du Colombier m = VLONG_MAX/base;
608ccd4a63SDavid du Colombier for(;; p++,ndig++) {
618ccd4a63SDavid du Colombier c = *p;
628ccd4a63SDavid du Colombier v = base;
638ccd4a63SDavid du Colombier if('0'<=c && c<='9')
648ccd4a63SDavid du Colombier v = c - '0';
658ccd4a63SDavid du Colombier else
668ccd4a63SDavid du Colombier if('a'<=c && c<='z')
678ccd4a63SDavid du Colombier v = c - 'a' + 10;
688ccd4a63SDavid du Colombier else
698ccd4a63SDavid du Colombier if('A'<=c && c<='Z')
708ccd4a63SDavid du Colombier v = c - 'A' + 10;
718ccd4a63SDavid du Colombier if(v >= base)
728ccd4a63SDavid du Colombier break;
738ccd4a63SDavid du Colombier if(n > m)
748ccd4a63SDavid du Colombier ovfl = 1;
758ccd4a63SDavid du Colombier nn = n*base + v;
768ccd4a63SDavid du Colombier if(nn < n)
778ccd4a63SDavid du Colombier ovfl = 1;
788ccd4a63SDavid du Colombier n = nn;
798ccd4a63SDavid du Colombier }
808ccd4a63SDavid du Colombier Return:
818ccd4a63SDavid du Colombier if(ndig == 0)
828ccd4a63SDavid du Colombier p = (char*)nptr;
838ccd4a63SDavid du Colombier if(endptr)
848ccd4a63SDavid du Colombier *endptr = p;
858ccd4a63SDavid du Colombier if(ovfl){
868ccd4a63SDavid du Colombier if(neg)
878ccd4a63SDavid du Colombier return VLONG_MIN;
888ccd4a63SDavid du Colombier return VLONG_MAX;
898ccd4a63SDavid du Colombier }
908ccd4a63SDavid du Colombier if(neg)
918ccd4a63SDavid du Colombier return -n;
928ccd4a63SDavid du Colombier return n;
938ccd4a63SDavid du Colombier }
94