xref: /inferno-os/libkern/strtoll.c (revision 46439007cf417cbd9ac8049bb4122c890097a0fa)
1 #include "lib9.h"
2 
3 vlong
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