scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

strtol.c (970B)


      1 #include <ctype.h>
      2 #include <errno.h>
      3 #include <limits.h>
      4 #include <stdlib.h>
      5 #include <string.h>
      6 
      7 #include "../libc.h"
      8 
      9 #undef strtol
     10 
     11 long
     12 strtol(const char * restrict ptr, char ** restrict end, int base)
     13 {
     14 	int d, sign = -1;
     15 	long n;
     16 	char *t, *s = (char *) ptr;
     17 
     18 	if (end)
     19 		*end = s;
     20 
     21 	while (isspace(*s))
     22 		++s;
     23 
     24 	switch (*s) {
     25 	case '-':
     26 		sign = 1;
     27 	case '+':
     28 		++s;
     29 	}
     30 
     31 	if (base == 0) {
     32 		if (*s == '0')
     33 			base = toupper(s[1]) == 'X' ? 16 : 8;
     34 		else
     35 			base = 10;
     36 	}
     37 	if (base == 16 && *s == '0' && toupper(s[1]) == 'X')
     38 		s += 2;
     39 
     40 	n = 0;
     41 	/* Compute n as a negative number to avoid overflow on LONG_MIN */
     42 	for (t = s; (d = _dtoi(*t)) < base; ++t) {
     43 		if (n < LONG_MIN/base)
     44 			goto overflow;
     45 		n *= base;
     46 		if (-d < LONG_MIN - n)
     47 			goto overflow;
     48 		n -= d;
     49 		if (n == LONG_MIN && sign < 0)
     50 			goto overflow;
     51 	}
     52 
     53 	if (end && t != s)
     54 		*end = t;
     55 
     56 	return n*sign;
     57 
     58 overflow:
     59 	if (end)
     60 		*end = t;
     61 	errno = ERANGE;
     62 
     63 	return sign < 0 ? LONG_MAX : LONG_MIN;
     64 }