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