mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-29 00:32:29 +00:00
parent
d50064a779
commit
39b0a9c03e
2 changed files with 103 additions and 77 deletions
|
@ -37,18 +37,18 @@
|
||||||
})
|
})
|
||||||
|
|
||||||
#define FP_BUFFER_GROW 48
|
#define FP_BUFFER_GROW 48
|
||||||
#define BUFFER \
|
#define BUFFER \
|
||||||
({ \
|
({ \
|
||||||
int c = READ; \
|
int c = READ; \
|
||||||
if (fpbufcur >= fpbufsize - 1) { \
|
if (fpbufcur >= fpbufsize - 1) { \
|
||||||
fpbufsize = fpbufsize + FP_BUFFER_GROW; \
|
fpbufsize = fpbufsize + FP_BUFFER_GROW; \
|
||||||
fpbuf = realloc(fpbuf, fpbufsize); \
|
fpbuf = realloc(fpbuf, fpbufsize); \
|
||||||
} \
|
} \
|
||||||
if (c != -1) { \
|
if (c != -1) { \
|
||||||
fpbuf[fpbufcur++] = c; \
|
fpbuf[fpbufcur++] = c; \
|
||||||
fpbuf[fpbufcur] = '\0'; \
|
fpbuf[fpbufcur] = '\0'; \
|
||||||
} \
|
} \
|
||||||
c; \
|
c; \
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -236,8 +236,9 @@ int __vcscanf(int callback(void *), //
|
||||||
case 'f':
|
case 'f':
|
||||||
case 'F':
|
case 'F':
|
||||||
case 'g':
|
case 'g':
|
||||||
case 'G': // floating point number
|
case 'G': // floating point number
|
||||||
if (!(charbytes == sizeof(char) || charbytes == sizeof(wchar_t))) {
|
if (!(charbytes == sizeof(char) ||
|
||||||
|
charbytes == sizeof(wchar_t))) {
|
||||||
items = -1;
|
items = -1;
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
|
@ -361,7 +362,8 @@ int __vcscanf(int callback(void *), //
|
||||||
c = BUFFER;
|
c = BUFFER;
|
||||||
do {
|
do {
|
||||||
bool isdigit = c >= '0' && c <= '9';
|
bool isdigit = c >= '0' && c <= '9';
|
||||||
bool isletter = (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
|
bool isletter =
|
||||||
|
(c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
|
||||||
if (!(c == '_' || isdigit || isletter)) {
|
if (!(c == '_' || isdigit || isletter)) {
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
|
@ -420,72 +422,76 @@ int __vcscanf(int callback(void *), //
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BufferFloatingPointNumber:
|
BufferFloatingPointNumber:
|
||||||
enum { INTEGER, FRACTIONAL, SIGN, EXPONENT } state = INTEGER;
|
enum { INTEGER, FRACTIONAL, SIGN, EXPONENT } state = INTEGER;
|
||||||
do {
|
do {
|
||||||
bool isdecdigit = c >= '0' && c <= '9';
|
bool isdecdigit = c >= '0' && c <= '9';
|
||||||
bool ishexdigit = (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
|
bool ishexdigit = (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
|
||||||
bool ispoint = c == '.' || c == ',';
|
bool ispoint = c == '.' || c == ',';
|
||||||
bool isdecexp = c == 'e' || c == 'E';
|
bool isdecexp = c == 'e' || c == 'E';
|
||||||
bool ishexp = c == 'p' || c == 'P';
|
bool ishexp = c == 'p' || c == 'P';
|
||||||
bool issign = c == '+' || c == '-';
|
bool issign = c == '+' || c == '-';
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case INTEGER:
|
case INTEGER:
|
||||||
case FRACTIONAL:
|
case FRACTIONAL:
|
||||||
if (isdecdigit || (hexadecimal && ishexdigit)) {
|
if (isdecdigit || (hexadecimal && ishexdigit)) {
|
||||||
goto Continue;
|
goto Continue;
|
||||||
} else if (state == INTEGER && ispoint) {
|
} else if (state == INTEGER && ispoint) {
|
||||||
state = FRACTIONAL;
|
state = FRACTIONAL;
|
||||||
goto Continue;
|
goto Continue;
|
||||||
} else if (isdecexp || (hexadecimal && ishexp)) {
|
} else if (isdecexp || (hexadecimal && ishexp)) {
|
||||||
state = SIGN;
|
state = SIGN;
|
||||||
goto Continue;
|
goto Continue;
|
||||||
} else {
|
} else {
|
||||||
goto Break;
|
|
||||||
}
|
|
||||||
case SIGN:
|
|
||||||
if (issign) {
|
|
||||||
state = EXPONENT;
|
|
||||||
goto Continue;
|
|
||||||
}
|
|
||||||
state = EXPONENT;
|
|
||||||
// fallthrough
|
|
||||||
case EXPONENT:
|
|
||||||
if (isdecdigit) {
|
|
||||||
goto Continue;
|
|
||||||
} else {
|
|
||||||
goto Break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
goto Break;
|
goto Break;
|
||||||
}
|
|
||||||
Continue:
|
|
||||||
continue;
|
|
||||||
Break:
|
|
||||||
if (c != -1 && unget) {
|
|
||||||
unget(c, arg);
|
|
||||||
}
|
}
|
||||||
break;
|
case SIGN:
|
||||||
} while ((c = BUFFER) != -1);
|
if (issign) {
|
||||||
GotFloatingPointNumber:
|
state = EXPONENT;
|
||||||
fp = strtod((char *)fpbuf, NULL);
|
goto Continue;
|
||||||
if (!discard) {
|
}
|
||||||
++items;
|
state = EXPONENT;
|
||||||
void *out = va_arg(va, void *);
|
// fallthrough
|
||||||
if (charbytes == sizeof(char)) {
|
case EXPONENT:
|
||||||
*(float *)out = (float)fp;
|
if (isdecdigit) {
|
||||||
} else {
|
goto Continue;
|
||||||
*(double *)out = (double)fp;
|
} else {
|
||||||
}
|
goto Break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
goto Break;
|
||||||
}
|
}
|
||||||
|
Continue:
|
||||||
|
continue;
|
||||||
|
Break:
|
||||||
|
if (c != -1 && unget) {
|
||||||
|
unget(c, arg);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} while ((c = BUFFER) != -1);
|
||||||
|
GotFloatingPointNumber:
|
||||||
|
fp = strtod((char *)fpbuf, NULL);
|
||||||
|
if (!discard) {
|
||||||
|
++items;
|
||||||
|
void *out = va_arg(va, void *);
|
||||||
|
if (charbytes == sizeof(char)) {
|
||||||
|
*(float *)out = (float)fp;
|
||||||
|
} else {
|
||||||
|
*(double *)out = (double)fp;
|
||||||
|
}
|
||||||
|
}
|
||||||
free(fpbuf);
|
free(fpbuf);
|
||||||
fpbuf = NULL;
|
fpbuf = NULL;
|
||||||
fpbufcur = fpbufsize = 0;
|
fpbufcur = fpbufsize = 0;
|
||||||
continue;
|
continue;
|
||||||
ReportConsumed:
|
ReportConsumed:
|
||||||
n_ptr = va_arg(va, int *);
|
n_ptr = va_arg(va, int *);
|
||||||
*n_ptr = consumed - 1; // minus lookahead
|
if (c != -1) {
|
||||||
|
*n_ptr = consumed - 1; // minus lookahead
|
||||||
|
} else {
|
||||||
|
*n_ptr = consumed;
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
DecodeString:
|
DecodeString:
|
||||||
bufsize = !width ? 32 : rawmode ? width : width + 1;
|
bufsize = !width ? 32 : rawmode ? width : width + 1;
|
||||||
|
@ -545,7 +551,7 @@ int __vcscanf(int callback(void *), //
|
||||||
}
|
}
|
||||||
++items;
|
++items;
|
||||||
if (ismalloc) {
|
if (ismalloc) {
|
||||||
*va_arg(va, char **) = (void *) buf;
|
*va_arg(va, char **) = (void *)buf;
|
||||||
}
|
}
|
||||||
buf = NULL;
|
buf = NULL;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -383,7 +383,8 @@ TEST(sscanf, floating_point_infinity) {
|
||||||
TEST(sscanf, floating_point_infinity_double_precision) {
|
TEST(sscanf, floating_point_infinity_double_precision) {
|
||||||
double a = 666.666, b = a, c = b, d = c, e = d, f = e, g = f;
|
double a = 666.666, b = a, c = b, d = c, e = d, f = e, g = f;
|
||||||
EXPECT_EQ(4, sscanf("inf +INF -iNf InF", "%lf %lf %lf %lf", &a, &b, &c, &d));
|
EXPECT_EQ(4, sscanf("inf +INF -iNf InF", "%lf %lf %lf %lf", &a, &b, &c, &d));
|
||||||
EXPECT_EQ(3, sscanf("+infinity -INFINITY iNfInItY", "%lf %lf %lf", &e, &f, &g));
|
EXPECT_EQ(3,
|
||||||
|
sscanf("+infinity -INFINITY iNfInItY", "%lf %lf %lf", &e, &f, &g));
|
||||||
EXPECT_TRUE(isinf(a));
|
EXPECT_TRUE(isinf(a));
|
||||||
EXPECT_TRUE(isinf(b));
|
EXPECT_TRUE(isinf(b));
|
||||||
EXPECT_TRUE(isinf(c));
|
EXPECT_TRUE(isinf(c));
|
||||||
|
@ -394,11 +395,14 @@ TEST(sscanf, floating_point_infinity_double_precision) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(sscanf, floating_point_documentation_examples) {
|
TEST(sscanf, floating_point_documentation_examples) {
|
||||||
float a = 666.666f, b = a, c = b, d = c, e = d, f = e, g = f, h = g, i = h, j = i;
|
float a = 666.666f, b = a, c = b, d = c, e = d, f = e, g = f, h = g, i = h,
|
||||||
|
j = i;
|
||||||
|
|
||||||
EXPECT_EQ(2, sscanf("111.11 -2.22", "%f %f", &a, &b));
|
EXPECT_EQ(2, sscanf("111.11 -2.22", "%f %f", &a, &b));
|
||||||
EXPECT_EQ(3, sscanf("Nan nan(2) inF", "%f %f %f", &c, &d, &e));
|
EXPECT_EQ(3, sscanf("Nan nan(2) inF", "%f %f %f", &c, &d, &e));
|
||||||
EXPECT_EQ(5, sscanf("0X1.BC70A3D70A3D7P+6 1.18973e+4932zzz -0.0000000123junk junk", "%f %f %f %f %f", &f, &g, &h, &i, &j));
|
EXPECT_EQ(
|
||||||
|
5, sscanf("0X1.BC70A3D70A3D7P+6 1.18973e+4932zzz -0.0000000123junk junk",
|
||||||
|
"%f %f %f %f %f", &f, &g, &h, &i, &j));
|
||||||
|
|
||||||
EXPECT_EQ(111.11f, a);
|
EXPECT_EQ(111.11f, a);
|
||||||
EXPECT_EQ(-2.22f, b);
|
EXPECT_EQ(-2.22f, b);
|
||||||
|
@ -413,11 +417,14 @@ TEST(sscanf, floating_point_documentation_examples) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(sscanf, floating_point_documentation_examples_double_precision) {
|
TEST(sscanf, floating_point_documentation_examples_double_precision) {
|
||||||
double a = 666.666, b = a, c = b, d = c, e = d, f = e, g = f, h = g, i = h, j = i;
|
double a = 666.666, b = a, c = b, d = c, e = d, f = e, g = f, h = g, i = h,
|
||||||
|
j = i;
|
||||||
|
|
||||||
EXPECT_EQ(2, sscanf("111.11 -2.22", "%lf %lf", &a, &b));
|
EXPECT_EQ(2, sscanf("111.11 -2.22", "%lf %lf", &a, &b));
|
||||||
EXPECT_EQ(3, sscanf("Nan nan(2) inF", "%lf %lf %lf", &c, &d, &e));
|
EXPECT_EQ(3, sscanf("Nan nan(2) inF", "%lf %lf %lf", &c, &d, &e));
|
||||||
EXPECT_EQ(5, sscanf("0X1.BC70A3D70A3D7P+6 1.18973e+4932zzz -0.0000000123junk junk", "%lf %lf %lf %lf %lf", &f, &g, &h, &i, &j));
|
EXPECT_EQ(
|
||||||
|
5, sscanf("0X1.BC70A3D70A3D7P+6 1.18973e+4932zzz -0.0000000123junk junk",
|
||||||
|
"%lf %lf %lf %lf %lf", &f, &g, &h, &i, &j));
|
||||||
|
|
||||||
EXPECT_EQ(111.11, a);
|
EXPECT_EQ(111.11, a);
|
||||||
EXPECT_EQ(-2.22, b);
|
EXPECT_EQ(-2.22, b);
|
||||||
|
@ -470,3 +477,16 @@ TEST(fscanf, wantDecimalButGotLetter_returnsZeroMatches) {
|
||||||
EXPECT_EQ(666, x);
|
EXPECT_EQ(666, x);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(scanf, n) {
|
||||||
|
int rc;
|
||||||
|
unsigned int a, b, c, d, port, len;
|
||||||
|
rc = sscanf("1.2.3.4:1848", "%u.%u.%u.%u:%u%n", &a, &b, &c, &d, &port, &len);
|
||||||
|
ASSERT_EQ(5, rc);
|
||||||
|
ASSERT_EQ(1, a);
|
||||||
|
ASSERT_EQ(2, b);
|
||||||
|
ASSERT_EQ(3, c);
|
||||||
|
ASSERT_EQ(4, d);
|
||||||
|
ASSERT_EQ(1848, port);
|
||||||
|
ASSERT_EQ(12, len);
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue