mirror of https://github.com/diegocr/libnix.git
60 lines
1.1 KiB
C
60 lines
1.1 KiB
C
#include <stdio.h>
|
|
#include <ctype.h>
|
|
#include <errno.h>
|
|
#include <limits.h>
|
|
#include <stdlib.h>
|
|
|
|
unsigned long strtoul(const char *nptr,char **endptr,int base)
|
|
{ const char *p=nptr,*q;
|
|
char c=0;
|
|
unsigned long r=0;
|
|
if(base<0||base==1||base>36)
|
|
{ if(endptr!=NULL)
|
|
*endptr=(char *)nptr;
|
|
return 0;
|
|
}
|
|
if(!(nptr && *nptr))
|
|
{ errno=EINVAL;
|
|
return 0;
|
|
}
|
|
while(isspace(*p))
|
|
p++;
|
|
if(*p=='-'||*p=='+')
|
|
c=*p++;
|
|
if(base==0)
|
|
{ if(p[0]=='0')
|
|
{ if(tolower(p[1])=='x'&&isxdigit(p[2]))
|
|
{ p+=2;
|
|
base=16; }
|
|
else
|
|
base=8;
|
|
}else
|
|
base=10;
|
|
}
|
|
q=p;
|
|
for(;;)
|
|
{ int a;
|
|
if(!isalnum(*q))
|
|
break;
|
|
a=isdigit(*q)?*q-'0':tolower(*q)-('a'-10);
|
|
if(a>=base)
|
|
break;
|
|
if(r>(ULONG_MAX-a)/base||r*base>ULONG_MAX-a)
|
|
{ errno=ERANGE; /* overflow */
|
|
r=ULONG_MAX; }
|
|
else
|
|
r=r*base+a;
|
|
q++;
|
|
}
|
|
if(q==p) /* Not a single number read */
|
|
{ if(endptr!=NULL)
|
|
*endptr=(char *)nptr;
|
|
return 0;
|
|
}
|
|
if(c=='-')
|
|
r=-r;
|
|
if(endptr!=NULL)
|
|
*endptr=(char *)q;
|
|
return r;
|
|
}
|