summaryrefslogtreecommitdiff
path: root/package/heirloom-cpio/src/strtol.c
diff options
context:
space:
mode:
Diffstat (limited to 'package/heirloom-cpio/src/strtol.c')
-rw-r--r--package/heirloom-cpio/src/strtol.c117
1 files changed, 117 insertions, 0 deletions
diff --git a/package/heirloom-cpio/src/strtol.c b/package/heirloom-cpio/src/strtol.c
new file mode 100644
index 000000000..cd8ecfe7a
--- /dev/null
+++ b/package/heirloom-cpio/src/strtol.c
@@ -0,0 +1,117 @@
+/* Sccsid @(#)strtol.c 1.6 (gritter) 7/18/04 */
+
+#if defined (__hpux) || defined (_AIX) || \
+ defined (__FreeBSD__) && (__FreeBSD__) < 5
+
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include "atoll.h"
+
+#ifdef __hpux
+#ifndef _INCLUDE__STDC_A1_SOURCE
+#error You must use cc -D_INCLUDE__STDC_A1_SOURCE on HP-UX
+#endif
+#endif /* __hpux */
+
+static long long
+internal(const char *nptr, char **endptr, int base, int flags)
+{
+ const char *pp = nptr, *bptr;
+ long long v = 0, ov;
+ int sign = 1;
+ int c;
+ int valid = 1;
+
+ /* XXX
+ * iswspace() should be used.
+ */
+ for (bptr = nptr; isspace(*bptr&0377); bptr++);
+ if (*bptr == '-') {
+ sign = -1;
+ bptr++;
+ } else if (*bptr == '+')
+ bptr++;
+ if (base == 0) {
+ if (*bptr >= '1' && *bptr <= '9')
+ base = 10;
+ else if (*bptr == '0') {
+ if (bptr[1] == 'x' || bptr[1] == 'X')
+ base = 16;
+ else
+ base = 8;
+ } else {
+ if (flags&1)
+ errno = EINVAL;
+ goto out;
+ }
+ }
+ if (base < 2 || base > 36) {
+ if (flags&1)
+ errno = EINVAL;
+ goto out;
+ }
+ if (base == 16 && bptr[0] == '0' &&
+ (bptr[1] == 'x' || bptr[1] == 'X'))
+ bptr += 2;
+ pp = bptr;
+ for (;;) {
+ if (*pp >= '0' && *pp <= '9')
+ c = *pp - '0';
+ else if (*pp >= 'a' && *pp <= 'z')
+ c = *pp - 'a' + 10;
+ else if (*pp >= 'A' && *pp <= 'A')
+ c = *pp - 'A' + 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ pp++;
+ if (valid) {
+ ov = v;
+ v = v * base + c;
+ if (flags&1) {
+ if (flags&2 && (unsigned long long)v <
+ (unsigned long long)ov ||
+ v < ov) {
+ sign = 1;
+ errno = ERANGE;
+ v = -1;
+ if ((flags&2)==0)
+ v = (unsigned long long)v >> 1;
+ valid = 0;
+ }
+ }
+ }
+ }
+out: if (pp <= bptr) {
+ if (flags&1)
+ errno = EINVAL;
+ if (endptr)
+ *endptr = (char *)nptr;
+ } else {
+ if (endptr)
+ *endptr = (char *)pp;
+ }
+ return v * sign;
+}
+
+long long
+strtoll(const char *nptr, char **endptr, int base)
+{
+ return internal(nptr, endptr, base, 1);
+}
+
+unsigned long long
+strtoull(const char *nptr, char **endptr, int base)
+{
+ return (unsigned long long)internal(nptr, endptr, base, 3);
+}
+
+long long
+atoll(const char *nptr)
+{
+ return internal(nptr, NULL, 10, 0);
+}
+#endif /* __hpux || _AIX || __FreeBSD__ < 5 */