diff options
author | Thorsten Lockert <tholo@cvs.openbsd.org> | 1996-04-27 19:43:32 +0000 |
---|---|---|
committer | Thorsten Lockert <tholo@cvs.openbsd.org> | 1996-04-27 19:43:32 +0000 |
commit | 49126961fd129e607f88970e81ab6d48baaecda0 (patch) | |
tree | 8168bd6a7b92392e99d483a83c51b3f8f7df113d /gnu/usr.bin/cvs/lib/strtoul.c | |
parent | 61aa6f7b30e536382606a49e9a65374b125db338 (diff) |
Latest public release from Cyclic; fixes numerous memory leaks and have
some performance improvements
Diffstat (limited to 'gnu/usr.bin/cvs/lib/strtoul.c')
-rw-r--r-- | gnu/usr.bin/cvs/lib/strtoul.c | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/gnu/usr.bin/cvs/lib/strtoul.c b/gnu/usr.bin/cvs/lib/strtoul.c new file mode 100644 index 00000000000..7d42c210f67 --- /dev/null +++ b/gnu/usr.bin/cvs/lib/strtoul.c @@ -0,0 +1,100 @@ +/* + * strtol : convert a string to long. + * + * Andy Wilson, 2-Oct-89. + */ + +#include <errno.h> +#include <ctype.h> +#include <stdio.h> + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifndef ULONG_MAX +#define ULONG_MAX ((unsigned long)(~0L)) /* 0xFFFFFFFF */ +#endif + +extern int errno; + +unsigned long +strtoul(s, ptr, base) + const char *s; char **ptr; int base; +{ + unsigned long total = 0; + unsigned digit; + const char *start=s; + int did_conversion=0; + int overflow = 0; + int negate = 0; + unsigned long maxdiv, maxrem; + + if (s==NULL) + { + errno = ERANGE; + if (!ptr) + *ptr = (char *)start; + return 0L; + } + + while (isspace(*s)) + s++; + if (*s == '+') + s++; + else if (*s == '-') + s++, negate = 1; + if (base==0 || base==16) /* the 'base==16' is for handling 0x */ + { + int tmp; + + /* + * try to infer base from the string + */ + if (*s != '0') + tmp = 10; /* doesn't start with 0 - assume decimal */ + else if (s[1] == 'X' || s[1] == 'x') + tmp = 16, s += 2; /* starts with 0x or 0X - hence hex */ + else + tmp = 8; /* starts with 0 - hence octal */ + if (base==0) + base = (int)tmp; + } + + maxdiv = ULONG_MAX / base; + maxrem = ULONG_MAX % base; + + while ((digit = *s) != '\0') + { + if (digit >= '0' && digit < ('0'+base)) + digit -= '0'; + else + if (base > 10) + { + if (digit >= 'a' && digit < ('a'+(base-10))) + digit = digit - 'a' + 10; + else if (digit >= 'A' && digit < ('A'+(base-10))) + digit = digit - 'A' + 10; + else + break; + } + else + break; + did_conversion = 1; + if (total > maxdiv + || (total == maxdiv && digit > maxrem)) + overflow = 1; + total = (total * base) + digit; + s++; + } + if (overflow) + { + errno = ERANGE; + if (ptr != NULL) + *ptr = (char *)s; + return (ULONG_MAX); + } + if (ptr != NULL) + *ptr = (char *) ((did_conversion) ? (char *)s : (char *)start); + return negate ? -total : total; +} |