Add first stab at SRFI 169 underscores support
This commit is contained in:
parent
55c6328241
commit
003068f575
70
c/read.h
70
c/read.h
|
@ -34,12 +34,62 @@ static int symchar(char c)
|
||||||
return !strchr(special, c);
|
return !strchr(special, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int read_digits(char *token, char **out_end, unsigned int radix,
|
||||||
|
uint64_t *out_value)
|
||||||
|
{
|
||||||
|
uint64_t value = 0;
|
||||||
|
int letterlimit, digit, was_digit_p, c;
|
||||||
|
|
||||||
|
if (!radix) {
|
||||||
|
radix = 10;
|
||||||
|
}
|
||||||
|
if (radix <= 10) {
|
||||||
|
letterlimit = 0;
|
||||||
|
} else if (radix <= 36) {
|
||||||
|
letterlimit = radix - 10;
|
||||||
|
} else {
|
||||||
|
letterlimit = 0;
|
||||||
|
}
|
||||||
|
was_digit_p = 0;
|
||||||
|
for (; (c = *token); token++) {
|
||||||
|
if (c == '_') {
|
||||||
|
if (was_digit_p) {
|
||||||
|
was_digit_p = 0;
|
||||||
|
continue;
|
||||||
|
} else if (value) {
|
||||||
|
lerror(ArgError, "More than one consecutive underscore");
|
||||||
|
} else {
|
||||||
|
lerror(ArgError, "Underscore before digits");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((c >= '0') && (c <= '9')) {
|
||||||
|
digit = c - '0';
|
||||||
|
} else if ((c >= 'A') && (c < 'A' + letterlimit)) {
|
||||||
|
digit = 10 + (c - 'A');
|
||||||
|
} else if ((c >= 'a') && (c < 'a' + letterlimit)) {
|
||||||
|
digit = 10 + (c - 'a');
|
||||||
|
} else if (value && !was_digit_p) {
|
||||||
|
lerror(ArgError, "Underscore after digits");
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
value *= radix;
|
||||||
|
value += digit;
|
||||||
|
was_digit_p = 1;
|
||||||
|
}
|
||||||
|
*out_end = token;
|
||||||
|
*out_value = value;
|
||||||
|
return was_digit_p;
|
||||||
|
}
|
||||||
|
|
||||||
int isnumtok_base(char *tok, value_t *pval, int base)
|
int isnumtok_base(char *tok, value_t *pval, int base)
|
||||||
{
|
{
|
||||||
char *end;
|
char *end;
|
||||||
int64_t i64;
|
int64_t i64;
|
||||||
uint64_t ui64;
|
uint64_t ui64;
|
||||||
double d;
|
double d;
|
||||||
|
int ok;
|
||||||
|
|
||||||
if (*tok == '\0')
|
if (*tok == '\0')
|
||||||
return 0;
|
return 0;
|
||||||
if (!((tok[0] == '0' && tok[1] == 'x') || (base >= 15)) &&
|
if (!((tok[0] == '0' && tok[1] == 'x') || (base >= 15)) &&
|
||||||
|
@ -89,10 +139,24 @@ int isnumtok_base(char *tok, value_t *pval, int base)
|
||||||
*pval = return_from_int64(i64);
|
*pval = return_from_int64(i64);
|
||||||
return (*end == '\0');
|
return (*end == '\0');
|
||||||
}
|
}
|
||||||
errno = 0;
|
if (tok[0] == '_') {
|
||||||
ui64 = strtoull(tok, &end, base);
|
|
||||||
if (errno)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
ok = 0;
|
||||||
|
if (tok[0] == '0') {
|
||||||
|
if (tok[1] == 'x') {
|
||||||
|
// TODO: We should get rid of 0x hex syntax: #x is enough.
|
||||||
|
if (!(ok = read_digits(tok + 2, &end, 16, &ui64))) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!ok) {
|
||||||
|
ok = read_digits(tok, &end, base, &ui64);
|
||||||
|
}
|
||||||
|
if (!ok) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if (pval)
|
if (pval)
|
||||||
*pval = return_from_uint64(ui64);
|
*pval = return_from_uint64(ui64);
|
||||||
return (*end == '\0');
|
return (*end == '\0');
|
||||||
|
|
Loading…
Reference in New Issue