os-workshop

same materials and sample source for RV32 OS projects
git clone http://frotz.net/git/os-workshop.git
Log | Files | Refs

atoi.c (3550B)


      1 /*
      2 ** Copyright 2001, Travis Geiselbrecht. All rights reserved.
      3 ** Distributed under the terms of the NewOS License.
      4 */
      5 /*
      6  * Copyright (c) 2008 Travis Geiselbrecht
      7  *
      8  * Use of this source code is governed by a MIT-style
      9  * license that can be found in the LICENSE file or at
     10  * https://opensource.org/licenses/MIT
     11  */
     12 
     13 #include <limits.h>
     14 #include <stdlib.h>
     15 #include <ctype.h>
     16 #include <errno.h>
     17 
     18 #define LONG_IS_INT 1
     19 
     20 static int hexval(char c) {
     21     if (c >= '0' && c <= '9')
     22         return c - '0';
     23     else if (c >= 'a' && c <= 'f')
     24         return c - 'a' + 10;
     25     else if (c >= 'A' && c <= 'F')
     26         return c - 'A' + 10;
     27 
     28     return 0;
     29 }
     30 
     31 int atoi(const char *num) {
     32 #if !LONG_IS_INT
     33     // XXX fail
     34 #else
     35     return atol(num);
     36 #endif
     37 }
     38 
     39 unsigned int atoui(const char *num) {
     40 #if !LONG_IS_INT
     41     // XXX fail
     42 #else
     43     return atoul(num);
     44 #endif
     45 }
     46 
     47 long atol(const char *num) {
     48     long value = 0;
     49     int neg = 0;
     50 
     51     if (num[0] == '0' && num[1] == 'x') {
     52         // hex
     53         num += 2;
     54         while (*num && isxdigit(*num))
     55             value = value * 16 + hexval(*num++);
     56     } else {
     57         // decimal
     58         if (num[0] == '-') {
     59             neg = 1;
     60             num++;
     61         }
     62         while (*num && isdigit(*num))
     63             value = value * 10 + *num++  - '0';
     64     }
     65 
     66     if (neg)
     67         value = -value;
     68 
     69     return value;
     70 }
     71 
     72 unsigned long atoul(const char *num) {
     73     unsigned long value = 0;
     74     if (num[0] == '0' && num[1] == 'x') {
     75         // hex
     76         num += 2;
     77         while (*num && isxdigit(*num))
     78             value = value * 16 + hexval(*num++);
     79     } else {
     80         // decimal
     81         while (*num && isdigit(*num))
     82             value = value * 10 + *num++  - '0';
     83     }
     84 
     85     return value;
     86 }
     87 
     88 unsigned long long atoull(const char *num) {
     89     unsigned long long value = 0;
     90     if (num[0] == '0' && num[1] == 'x') {
     91         // hex
     92         num += 2;
     93         while (*num && isxdigit(*num))
     94             value = value * 16 + hexval(*num++);
     95     } else {
     96         // decimal
     97         while (*num && isdigit(*num))
     98             value = value * 10 + *num++  - '0';
     99     }
    100 
    101     return value;
    102 }
    103 
    104 unsigned long strtoul(const char *nptr, char **endptr, int base) {
    105     int neg = 0;
    106     unsigned long ret = 0;
    107 
    108     if (base < 0 || base == 1 || base > 36) {
    109         errno = EINVAL;
    110         return 0;
    111     }
    112 
    113     while (isspace(*nptr)) {
    114         nptr++;
    115     }
    116 
    117     if (*nptr == '+') {
    118         nptr++;
    119     } else if (*nptr == '-') {
    120         neg = 1;
    121         nptr++;
    122     }
    123 
    124     if ((base == 0 || base == 16) && nptr[0] == '0' && nptr[1] == 'x') {
    125         base = 16;
    126         nptr += 2;
    127     } else if (base == 0 && nptr[0] == '0') {
    128         base = 8;
    129         nptr++;
    130     } else if (base == 0) {
    131         base = 10;
    132     }
    133 
    134     for (;;) {
    135         char c = *nptr;
    136         int v = -1;
    137         unsigned long new_ret;
    138 
    139         if (c >= 'A' && c <= 'Z') {
    140             v = c - 'A' + 10;
    141         } else if (c >= 'a' && c <= 'z') {
    142             v = c - 'a' + 10;
    143         } else if (c >= '0' && c <= '9') {
    144             v = c - '0';
    145         }
    146 
    147         if (v < 0 || v >= base) {
    148             if (endptr) {
    149                 *endptr = (char *) nptr;
    150             }
    151             break;
    152         }
    153 
    154         new_ret = ret * base;
    155         if (new_ret / base != ret ||
    156                 new_ret + v < new_ret ||
    157                 ret == ULONG_MAX) {
    158             ret = ULONG_MAX;
    159             errno = ERANGE;
    160         } else {
    161             ret = new_ret + v;
    162         }
    163 
    164         nptr++;
    165     }
    166 
    167     if (neg && ret != ULONG_MAX) {
    168         ret = -ret;
    169     }
    170 
    171     return ret;
    172 }