-
Notifications
You must be signed in to change notification settings - Fork 59
/
Copy pathstdlib.c
124 lines (104 loc) · 2.58 KB
/
stdlib.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/**
* \file
* \brief Standard libc library functions.
*/
/*
* Copyright (c) 2007-2011, ETH Zurich.
* All rights reserved.
*
* This file is distributed under the terms in the attached LICENSE file.
* If you do not find this file, copies can be found by writing to:
* ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group.
*/
#include <stddef.h>
#include <stdlib.h>
#include <assert.h>
/*
* Copied here, as there are conflicting types between oldc and newlib
*/
static inline int
isdigit(int c)
{
return '0' <= c && c <= '9';
}
static inline int
isxdigit(int c)
{
return isdigit(c) || ('A' <= c && c <= 'F') || ('a' <= c && c <= 'f');
}
static inline int
islower(int c)
{
return 'a' <= c && c <= 'z';
}
/**
* \brief Convert ASCII digit to integer.
*
* Converts an ASCII digit to the corresponding integer digit. Handles
* hexadecimal digits. Returns -1 on error.
*
* \param c ASCII digit to convert
*
* \return Integer digit corresponding to 'c' or -1 on error.
*/
static inline int
ascii_to_int(int c)
{
if(!isxdigit(c)) {
return -1;
}
if(isdigit(c)) { // c in ['0'..'9']
return c - '0';
}
if(islower(c)) { // c in ['a'..'f']
return 10 + c - 'a';
} else { // c in ['A'..'F']
return 10 + c - 'A';
}
}
/*
* XXX doesn't actually deal with a sign character!!!
*/
long int strtol(const char *nptr, char **endptr, int base)
{
assert(base == 10 || base == 16);
long int retval = 0;
size_t i;
for(i = 0;
(base == 10 && isdigit((int)nptr[i])) || (base == 16 && isxdigit((int)nptr[i]));
i++) {
// Shift and add a digit
retval = retval * base + ascii_to_int(nptr[i]);
}
if (endptr) {
*endptr = (char *) &nptr[i];
}
return retval;
}
unsigned long int strtoul(const char *nptr, char **endptr, int base)
{
assert(base == 10 || base == 16);
unsigned long int retval = 0;
size_t i;
for(i = 0;
(base == 10 && isdigit((int)nptr[i])) || (base == 16 && isxdigit((int)nptr[i]));
i++) {
// Shift and add a digit
retval = retval * base + ascii_to_int(nptr[i]);
}
if (endptr) {
*endptr = (char *) &nptr[i];
}
return retval;
}
/*
* Comaptibility for long long.. we don't implement those in the kernel
*/
unsigned long long strtoull(const char *nptr, char **endptr, int base)
{
return strtoul(nptr, endptr, base);
}
long long strtoll(const char *nptr, char **endptr, int base)
{
return strtol(nptr, endptr, base);
}