/* Copyright (C) 2008 Emmanuel Varoquaux
This file is part of XOS.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see . */
#include
#include "ctype.h"
#include
#include
#include
#include "misc.h"
static const char digits_lc[] = "0123456789abcdefghijklmnopqrstuvwxyz";
static const char digits_uc[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
long __attribute__ ((weak, visibility ("default"))) strtol(const char *str, char **endptr, int base)
{
int negative;
long val;
char *p;
int i;
if (base != 0 && (base < 2 || base > 36)) {
errno = EINVAL;
return 0;
}
while (__isspace(*str))
str++;
if (*str == '+') {
negative = 0;
str++;
}
else if (*str == '-') {
negative = 1;
str++;
}
else
negative = 0;
if (base == 0) {
if (!strncmp(str, "0x", 2) || !strncmp(str, "0X", 2)) {
base = 16;
str += 2;
}
else if (*str == '0') {
base = 8;
str++;
}
else
base = 10;
}
else if (base == 16)
if (!strncmp(str, "0x", 2) || !strncmp(str, "0X", 2))
str += 2;
val = 0;
while (*str) {
if ((p = strchr(digits_lc, *str)))
i = p - digits_lc;
else if ((p = strchr(digits_uc, *str)))
i = p - digits_uc;
else
break;
if (i >= base)
break;
if (!negative) {
if (val > (LONG_MAX - i) / base) {
if (endptr)
*endptr = strchr(str, '\0');
errno = ERANGE;
return LONG_MAX;
}
val = val * base + i;
}
else {
if (val < (LONG_MIN + i) / base) {
if (endptr)
*endptr = strchr(str, '\0');
errno = ERANGE;
return LONG_MIN;
}
val = val * base - i;
}
str++;
}
if (endptr)
*endptr = const_cast(char *, str);
return val;
}
unsigned long __attribute__ ((weak, visibility ("default"))) strtoul(const char *str, char **endptr, int base)
{
int negative;
unsigned long val;
char *p;
int i;
if (base != 0 && (base < 2 || base > 36)) {
errno = EINVAL;
return 0;
}
while (__isspace(*str))
str++;
if (*str == '+') {
negative = 0;
str++;
}
else if (*str == '-') {
negative = 1;
str++;
}
else
negative = 0;
if (base == 0) {
if (!strncmp(str, "0x", 2) || !strncmp(str, "0X", 2)) {
base = 16;
str += 2;
}
else if (*str == '0') {
base = 8;
str++;
}
else
base = 10;
}
else if (base == 16)
if (!strncmp(str, "0x", 2) || !strncmp(str, "0X", 2))
str += 2;
val = 0;
while (*str) {
if ((p = strchr(digits_lc, *str)))
i = p - digits_lc;
else if ((p = strchr(digits_uc, *str)))
i = p - digits_uc;
else
break;
if (i >= base)
break;
if (val > (ULONG_MAX - i) / base) {
if (endptr)
*endptr = strchr(str, '\0');
errno = ERANGE;
return ULONG_MAX;
}
val = val * base + i;
str++;
}
if (endptr)
*endptr = const_cast(char *, str);
return !negative ? val : -val;
}