/* 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; }