xref: /plan9/sys/src/cmd/unix/drawterm/libc/strtoll.c (revision ec59a3ddbfceee0efe34584c2c9981a5e5ff1ec4)
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