micropython/py/strtonum.c
Damien George c5966128c7 Implement proper exception type hierarchy.
Each built-in exception is now a type, with base type BaseException.
C exceptions are created by passing a pointer to the exception type to
make an instance of.  When raising an exception from the VM, an
instance is created automatically if an exception type is raised (as
opposed to an exception instance).

Exception matching (RT_BINARY_OP_EXCEPTION_MATCH) is now proper.

Handling of parse error changed to match new exceptions.

mp_const_type renamed to mp_type_type for consistency.
2014-02-15 16:10:44 +00:00

98 lines
2.2 KiB
C

#if defined(UNIX)
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
#include "misc.h"
#include "mpconfig.h"
#include "qstr.h"
#include "nlr.h"
#include "obj.h"
long strtonum(const char *restrict s, int base) {
int c, neg = 0;
const char *p = s;
char *num;
long found;
// check radix base
if ((base != 0 && base < 2) || base > 36) {
nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "ValueError: int() arg 2 must be >=2 and <= 36"));
}
// skip surrounded whitespace
while (isspace((c = *(p++))));
if (c == 0) {
goto value_error;
}
// preced sign
if (c == '+' || c == '-') {
neg = - (c == '-');
c = *(p++);
}
// find real radix base, and strip preced '0x', '0o' and '0b'
// TODO somehow merge with similar code in parse.c
if ((base == 0 || base == 16) && c == '0') {
c = *(p++);
if ((c | 32) == 'x') {
base = 16;
} else if (base == 0 && (c | 32) == 'o') {
base = 8;
} else if (base == 0 && (c | 32) == 'b') {
base = 2;
} else {
base = 10;
p -= 2;
}
} else if (base == 8 && c == '0') {
c = *(p++);
if ((c | 32) != 'o') {
p -= 2;
}
} else if (base == 2 && c == '0') {
c = *(p++);
if ((c | 32) != 'b') {
p -= 2;
}
} else {
if (base == 0) base = 10;
p--;
}
errno = 0;
found = strtol(p, &num, base);
if (errno) {
goto value_error;
} else if (found && *(num) == 0) {
goto done;
} else if (found || num != p) {
goto check_tail_space;
} else {
goto value_error;
}
check_tail_space:
if (*(num) != 0) {
while (isspace((c = *(num++))));
if (c != 0) {
goto value_error;
}
}
done:
return (found ^ neg) - neg;
value_error:
nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid literal for int() with base %d: '%s'", base, s));
}
#else /* defined(UNIX) */
long strtonum(const char *restrict s, int base) {
// TODO port strtol to stm
return 0;
}
#endif /* defined(UNIX) */