Refactor read_unsigned to prepare for pluggable atod
This commit is contained in:
parent
8bcfc139f7
commit
be33d016e9
|
@ -11,3 +11,4 @@ GTAGS
|
|||
_build
|
||||
_static
|
||||
_template
|
||||
.DS_Store
|
||||
|
|
|
@ -213,6 +213,69 @@ strcpy(char *dst, const char *src)
|
|||
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
|
||||
|
||||
#if PIC_ENABLE_STDIO
|
||||
|
|
|
@ -237,104 +237,58 @@ read_uinteger(pic_state *pic, struct pic_port *port, int c)
|
|||
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
|
||||
read_unsigned(pic_state *pic, struct pic_port *port, int c)
|
||||
{
|
||||
unsigned u;
|
||||
int exp, s, i, e;
|
||||
#define ATOF_BUF_SIZE (64)
|
||||
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);
|
||||
|
||||
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
|
||||
case '.': {
|
||||
double f, g, h;
|
||||
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 (! isdigit(c)) {
|
||||
read_error(pic, "expected one or more digits", pic_list1(pic, pic_char_value(c)));
|
||||
}
|
||||
buf[idx++] = (char )c;
|
||||
while (isdigit(c = peek(pic, port)) && idx < ATOF_BUF_SIZE) {
|
||||
buf[idx++] = (char )next(pic, port);
|
||||
}
|
||||
if ('.' == peek(pic, port) && idx < ATOF_BUF_SIZE) {
|
||||
dpe++;
|
||||
buf[idx++] = (char )next(pic, port);
|
||||
while (isdigit(c = peek(pic, port)) && idx < ATOF_BUF_SIZE) {
|
||||
buf[idx++] = (char )next(pic, port);
|
||||
}
|
||||
}
|
||||
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:
|
||||
exp = read_suffix(pic, port);
|
||||
if (exp >= 0) {
|
||||
s = 0;
|
||||
} else {
|
||||
exp = -exp;
|
||||
s = 1;
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
if (dpe == 0 && pic_valid_int(flt))
|
||||
return pic_int_value((int )flt);
|
||||
return pic_float_value(flt);
|
||||
}
|
||||
|
||||
static pic_value
|
||||
|
@ -346,7 +300,7 @@ read_number(pic_state *pic, struct pic_port *port, int c)
|
|||
static pic_value
|
||||
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));
|
||||
} else {
|
||||
return pic_float_value(-pic_float(n));
|
||||
|
|
Loading…
Reference in New Issue