00001
00002
00003
00004
00005
00006
00007 #include <ctype.h>
00008 #include <errno.h>
00009 #include <limits.h>
00010 #include <stdlib.h>
00011
00012 static unsigned long
00013 string2long(register const char *nptr, char **endptr,
00014 int base, int is_signed);
00015
00016 long int
00017 strtol(register const char *nptr, char **endptr, int base)
00018 {
00019 return (signed long)string2long(nptr, endptr, base, 1);
00020 }
00021
00022 unsigned long int
00023 strtoul(register const char *nptr, char **endptr, int base)
00024 {
00025 return (unsigned long)string2long(nptr, endptr, base, 0);
00026 }
00027
00028 #define between(a, c, z) ((unsigned) ((c) - (a)) <= (unsigned) ((z) - (a)))
00029
00030 static unsigned long
00031 string2long(register const char *nptr, char ** const endptr,
00032 int base, int is_signed)
00033 {
00034 register unsigned int v;
00035 register unsigned long val = 0;
00036 register int c;
00037 int ovfl = 0, sign = 1;
00038 const char *startnptr = nptr, *nrstart;
00039
00040 if (endptr) *endptr = (char *)nptr;
00041 while (isspace(*nptr)) nptr++;
00042 c = *nptr;
00043
00044 if (c == '-' || c == '+') {
00045 if (c == '-') sign = -1;
00046 nptr++;
00047 }
00048 nrstart = nptr;
00049
00050
00051 if (base == 0)
00052 if (*nptr == '0')
00053 if (*++nptr == 'x' || *nptr == 'X') {
00054 base = 16;
00055 nptr++;
00056 }
00057 else base = 8;
00058 else base = 10;
00059 else if (base==16 && *nptr=='0' && (*++nptr =='x' || *nptr =='X'))
00060 nptr++;
00061
00062 for (;;) {
00063 c = *nptr;
00064 if (between('0', c, '9')) {
00065 v = c - '0';
00066 } else
00067 if (between('a', c, 'z')) {
00068 v = c - 'a' + 0xa;
00069 } else
00070 if (between('A', c, 'Z')) {
00071 v = c - 'A' + 0xA;
00072 } else {
00073 break;
00074 }
00075 if (v >= base) break;
00076 if (val > (ULONG_MAX - v) / base) ovfl++;
00077 val = (val * base) + v;
00078 nptr++;
00079 }
00080 if (endptr) {
00081 if (nrstart == nptr) *endptr = (char *)startnptr;
00082 else *endptr = (char *)nptr;
00083 }
00084
00085 if (!ovfl) {
00086
00087 if (is_signed
00088 && ( (sign < 0 && val > -(unsigned long)LONG_MIN)
00089 || (sign > 0 && val > LONG_MAX)))
00090 ovfl++;
00091 }
00092
00093 if (ovfl) {
00094 errno = ERANGE;
00095 if (is_signed)
00096 if (sign < 0) return LONG_MIN;
00097 else return LONG_MAX;
00098 else return ULONG_MAX;
00099 }
00100 return (long) sign * val;
00101 }