//----------------------------------------------------------------------------// // GNU GPL OS/K // // // // Desc: strto*l() family // // // // // // Copyright © 2018-2020 The OS/K Team // // // // This file is part of OS/K. // // // // OS/K 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 // // any later version. // // // // OS/K 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 OS/K. If not, see . // //----------------------------------------------------------------------------// #include #include long strtol(const char *str, char **endp, int base) { ulong n; bool neg = 0; const char *save, *start = str; assert(str != NULL); char c = *str; // Ignore leading spaces while (isspace(c)) { c = *str++; } // Accept any +/-'s, whatever the base // In particular we accept things like "-0xF" if (c == '+') c = *str++; else if (c == '-') { c = *str++; neg = 1; } // Accept 0/0b/0B/0x/0X and guess base if needed if (c == '0') { c = *str++; if ((base == 0 || base == 16) && (c == 'x' || c == 'X')) { c = *str++; base = 16; } else if ((base == 0 || base == 2) && (c == 'b' || c == 'B')) { c = *str++; base = 2; } else if (base == 0) base = 8; } // base==0 but no leading '0' - assume it's decimal if (base == 0) base = 10; // // Extract the number from the string // We do not check whether the number actually fits // That's why our accumulator 'n' needs to be unsigned, otherwise // containing a number too large would cause a signed overflow and UB // save = str; for (n = 0;; c = *str) { if (isdigit(c)) c -= '0'; else if (isalpha(c)) c -= isupper(c) ? 'A' - 10 : 'a' - 10; else break; if (c >= base) break; else { str++; n = (n * base) + c; } } // Save where we stopped in *endp (optional) // If 'str' is still '== save', no digit were consummed if (endp != NULL) *endp = (char *)(str == save ? start : str); return neg ? -(long)n : (long)n; } // // Made from the code above by removing "neg" // ulong strtoul(const char *str, char **endp, int base) { ulong n; const char *save, *start = str; assert(str != NULL); char c = *str; while (isspace(c)) { c = *str++; } if (c == '+') c = *str++; if (c == '0') { c = *str++; if ((base == 0 || base == 16) && (c == 'x' || c == 'X')) { c = *str++; base = 16; } else if ((base == 0 || base == 2) && (c == 'b' || c == 'B')) { c = *str++; base = 2; } else if (base == 0) base = 8; } if (base == 0) base = 10; save = str; for (n = 0;; c = *str) { if (isdigit(c)) c -= '0'; else if (isalpha(c)) c -= isupper(c) ? 'A' - 10 : 'a' - 10; else break; if (c >= base) break; else { str++; n = (n * base) + c; } } if (endp != NULL) *endp = (char *)(str == save ? start : str); return (long)n; }