1 /* Copyright (C) 2002 Manuel Novoa III
2 * From my (incomplete) stdlib library for linux and (soon) elks.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, see
16 * <http://www.gnu.org/licenses/>.
18 * Adapted for Betaflight by Petr Ledvina, 2018
28 #include "common/utils.h"
30 #define _STRTO_ENDPTR 1
32 unsigned long _strto_l(const char * str
, char ** endptr
, int base
, int sflag
)
34 unsigned long number
, cutoff
;
36 const char *fail_char
;
37 #define SET_FAIL(X) fail_char = (X)
39 #define SET_FAIL(X) ((void)(X)) /* Keep side effects. */
41 unsigned char negative
, digit
, cutoff_digit
;
45 while (isspace(*str
)) { /* Skip leading whitespace. */
49 /* Handle optional sign. */
53 negative
= 1; /* Fall through to increment str. */
59 if (!base
|| base
== 16 || base
== 2) { /* Either dynamic (base = 0) or base with 0[xb] prefix. */
62 if ((!base
|| base
== 16) && tolower(*str
) == 'x') {
65 } else if ((!base
|| base
== 2) && tolower(*str
) == 'b') {
76 if (((unsigned)(base
- 2)) < 35) { /* Legal base. */
77 cutoff_digit
= ULONG_MAX
% base
;
78 cutoff
= ULONG_MAX
/ base
;
80 digit
= ( (*str
- '0') <= 9)
81 ? /* 0..9 */ (*str
- '0')
82 : /* else */ (((0x20 | *str
) >= 'a') /* WARNING: assumes ascii. */
83 ? /* >= A/a */ ((0x20 | *str
) - ('a' - 10))
84 : /* else */ 40 /* bad value */);
93 || ((number
== cutoff
) && (digit
> cutoff_digit
))) {
97 number
= number
* base
+ digit
;
104 *endptr
= (char *) fail_char
;
109 unsigned long tmp
= (negative
110 ? ((unsigned long)(-(1+LONG_MIN
)))+1
112 if (sflag
&& (number
> tmp
)) {
117 return negative
? (unsigned long)(-((long)number
)) : number
;
120 long strtol(const char * str
, char ** endptr
, int base
)
122 return _strto_l(str
, endptr
, base
, 1);
125 unsigned long strtoul(const char * str
, char ** endptr
, int base
)
127 return _strto_l(str
, endptr
, base
, 0);
130 int atoi(const char *str
)
132 return strtol(str
, NULL
, 10);