Refactor read_unsigned to prepare for pluggable atod
This commit is contained in:
parent
8bcfc139f7
commit
be33d016e9
|
@ -11,3 +11,4 @@ GTAGS
|
||||||
_build
|
_build
|
||||||
_static
|
_static
|
||||||
_template
|
_template
|
||||||
|
.DS_Store
|
||||||
|
|
|
@ -213,6 +213,69 @@ strcpy(char *dst, const char *src)
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PIC_INLINE double
|
||||||
|
atof(const char *nptr)
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
double f, g, h;
|
||||||
|
int exp, s, i, e;
|
||||||
|
unsigned u;
|
||||||
|
|
||||||
|
/* note that picrin_read always assures that *nptr is a digit, never a '+' or '-' */
|
||||||
|
/* in other words, the result of atof will always be positive */
|
||||||
|
|
||||||
|
/* mantissa */
|
||||||
|
/* pre '.' */
|
||||||
|
u = *nptr++ - '0';
|
||||||
|
while (isdigit(c = *nptr)) {
|
||||||
|
u = u * 10 + (*nptr++ - '0');
|
||||||
|
}
|
||||||
|
if (c == '.') {
|
||||||
|
/* after '.' */
|
||||||
|
g = 0, e = 0;
|
||||||
|
while (isdigit(c = *nptr)) {
|
||||||
|
g = g * 10 + (*nptr++ - '0');
|
||||||
|
e++;
|
||||||
|
}
|
||||||
|
h = 1.0;
|
||||||
|
while (e-- > 0) {
|
||||||
|
h /= 10;
|
||||||
|
}
|
||||||
|
f = u + g * h;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
f = u;
|
||||||
|
}
|
||||||
|
/* suffix, i.e., exponent */
|
||||||
|
s = 0;
|
||||||
|
exp = 0;
|
||||||
|
c = *nptr;
|
||||||
|
|
||||||
|
if (c == 'e' && c == 'E') {
|
||||||
|
nptr++;
|
||||||
|
switch ((c = *nptr++)) {
|
||||||
|
case '-':
|
||||||
|
s = 1;
|
||||||
|
case '+':
|
||||||
|
c = *nptr++;
|
||||||
|
default:
|
||||||
|
exp = c - '0';
|
||||||
|
while (isdigit(c = *nptr)) {
|
||||||
|
exp = exp * 10 + (*nptr++ - '0');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
e = 10;
|
||||||
|
for (i = 0; exp; ++i) {
|
||||||
|
if ((exp & 1) != 0) {
|
||||||
|
f = s ? f / e : (f * e);
|
||||||
|
}
|
||||||
|
e *= e;
|
||||||
|
exp >>= 1;
|
||||||
|
}
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if PIC_ENABLE_STDIO
|
#if PIC_ENABLE_STDIO
|
||||||
|
|
|
@ -237,104 +237,58 @@ read_uinteger(pic_state *pic, struct pic_port *port, int c)
|
||||||
return u;
|
return u;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
read_suffix(pic_state *pic, struct pic_port *port)
|
|
||||||
{
|
|
||||||
int c, s = 1;
|
|
||||||
|
|
||||||
c = peek(pic, port);
|
|
||||||
|
|
||||||
if (c != 'e' && c != 'E') {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
next(pic, port);
|
|
||||||
|
|
||||||
switch ((c = next(pic, port))) {
|
|
||||||
case '-':
|
|
||||||
s = -1;
|
|
||||||
case '+':
|
|
||||||
c = next(pic, port);
|
|
||||||
default:
|
|
||||||
return s * read_uinteger(pic, port, c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static pic_value
|
static pic_value
|
||||||
read_unsigned(pic_state *pic, struct pic_port *port, int c)
|
read_unsigned(pic_state *pic, struct pic_port *port, int c)
|
||||||
{
|
{
|
||||||
unsigned u;
|
#define ATOF_BUF_SIZE (64)
|
||||||
int exp, s, i, e;
|
char buf[ATOF_BUF_SIZE];
|
||||||
|
double flt;
|
||||||
|
int idx = 0; /* index into buffer */
|
||||||
|
int dpe = 0; /* the number of '.' or 'e' characters seen */
|
||||||
|
|
||||||
u = read_uinteger(pic, port, c);
|
if (! isdigit(c)) {
|
||||||
|
read_error(pic, "expected one or more digits", pic_list1(pic, pic_char_value(c)));
|
||||||
switch (peek(pic, port)) {
|
|
||||||
#if PIC_ENABLE_LIBC
|
|
||||||
case '.': {
|
|
||||||
char buf[256];
|
|
||||||
i = sprintf(buf, "%d", u);
|
|
||||||
buf[i++] = next(pic, port);
|
|
||||||
while (isdigit(c = peek(pic, port))) {
|
|
||||||
buf[i++] = next(pic, port);
|
|
||||||
}
|
|
||||||
sprintf(buf + i, "e%d", read_suffix(pic, port));
|
|
||||||
return pic_float_value(atof(buf));
|
|
||||||
}
|
}
|
||||||
#else
|
buf[idx++] = (char )c;
|
||||||
case '.': {
|
while (isdigit(c = peek(pic, port)) && idx < ATOF_BUF_SIZE) {
|
||||||
double f, g, h;
|
buf[idx++] = (char )next(pic, port);
|
||||||
next(pic, port);
|
|
||||||
g = 0, e = 0;
|
|
||||||
while (isdigit(c = peek(pic, port))) {
|
|
||||||
g = g * 10 + (next(pic, port) - '0');
|
|
||||||
e++;
|
|
||||||
}
|
|
||||||
h = 1.0;
|
|
||||||
while (e-- > 0) {
|
|
||||||
h /= 10;
|
|
||||||
}
|
|
||||||
f = u + g * h;
|
|
||||||
|
|
||||||
exp = read_suffix(pic, port);
|
|
||||||
if (exp >= 0) {
|
|
||||||
s = 0;
|
|
||||||
} else {
|
|
||||||
exp = -exp;
|
|
||||||
s = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
e = 10;
|
|
||||||
for (i = 0; exp; ++i) {
|
|
||||||
if ((exp & 1) != 0) {
|
|
||||||
f = s ? f / e : (f * e);
|
|
||||||
}
|
|
||||||
e *= e;
|
|
||||||
exp >>= 1;
|
|
||||||
}
|
|
||||||
return pic_float_value(f);
|
|
||||||
}
|
}
|
||||||
#endif
|
if ('.' == peek(pic, port) && idx < ATOF_BUF_SIZE) {
|
||||||
|
dpe++;
|
||||||
default:
|
buf[idx++] = (char )next(pic, port);
|
||||||
exp = read_suffix(pic, port);
|
while (isdigit(c = peek(pic, port)) && idx < ATOF_BUF_SIZE) {
|
||||||
if (exp >= 0) {
|
buf[idx++] = (char )next(pic, port);
|
||||||
s = 0;
|
|
||||||
} else {
|
|
||||||
exp = -exp;
|
|
||||||
s = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
e = 10;
|
|
||||||
for (i = 0; exp; ++i) {
|
|
||||||
if ((exp & 1) != 0) {
|
|
||||||
u = s ? u / e : (u * e);
|
|
||||||
}
|
|
||||||
e *= e;
|
|
||||||
exp >>= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return pic_int_value(u);
|
|
||||||
}
|
}
|
||||||
|
c = peek(pic, port);
|
||||||
|
|
||||||
|
if ((c == 'e' || c == 'E') && idx < (ATOF_BUF_SIZE - 2)) {
|
||||||
|
dpe++;
|
||||||
|
buf[idx++] = (char )next(pic, port);
|
||||||
|
switch ((c = peek(pic, port))) {
|
||||||
|
case '-':
|
||||||
|
case '+':
|
||||||
|
buf[idx++] = (char )next(pic, port);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (! isdigit(peek(pic, port))) {
|
||||||
|
read_error(pic, "expected one or more digits", pic_list1(pic, pic_char_value(c)));
|
||||||
|
}
|
||||||
|
while (isdigit(c = peek(pic, port)) && idx < ATOF_BUF_SIZE) {
|
||||||
|
buf[idx++] = (char )next(pic, port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (idx >= ATOF_BUF_SIZE)
|
||||||
|
read_error(pic, "number too large",
|
||||||
|
pic_obj_value(pic_make_str(pic, (const char *)buf, ATOF_BUF_SIZE)));
|
||||||
|
buf[idx] = 0;
|
||||||
|
flt = atof(buf);
|
||||||
|
|
||||||
|
if (dpe == 0 && pic_valid_int(flt))
|
||||||
|
return pic_int_value((int )flt);
|
||||||
|
return pic_float_value(flt);
|
||||||
}
|
}
|
||||||
|
|
||||||
static pic_value
|
static pic_value
|
||||||
|
@ -346,7 +300,7 @@ read_number(pic_state *pic, struct pic_port *port, int c)
|
||||||
static pic_value
|
static pic_value
|
||||||
negate(pic_value n)
|
negate(pic_value n)
|
||||||
{
|
{
|
||||||
if (pic_int_p(n)) {
|
if (pic_int_p(n) && (INT_MIN != pic_int(n))) {
|
||||||
return pic_int_value(-pic_int(n));
|
return pic_int_value(-pic_int(n));
|
||||||
} else {
|
} else {
|
||||||
return pic_float_value(-pic_float(n));
|
return pic_float_value(-pic_float(n));
|
||||||
|
|
Loading…
Reference in New Issue