From 2215b3c2677fe4555402c65c7fb0f1e104a80739 Mon Sep 17 00:00:00 2001 From: Lephenixnoir Date: Sun, 14 Jan 2024 17:30:30 +0100 Subject: [PATCH] stdio: make all scanf tests pass The tests are still far from exhaustive but that's a good start. --- src/stdio/scanf/scan.c | 70 ++++++++++-------------------------------- src/stdlib/strto_int.c | 3 ++ src/stdlib/strtod.c | 2 +- src/stdlib/strtof.c | 2 +- src/stdlib/strtol.c | 2 +- src/stdlib/strtold.c | 2 +- src/stdlib/strtoll.c | 2 +- src/stdlib/strtoul.c | 2 +- src/stdlib/strtoull.c | 2 +- 9 files changed, 26 insertions(+), 61 deletions(-) diff --git a/src/stdio/scanf/scan.c b/src/stdio/scanf/scan.c index b1aff5a..9bef20b 100644 --- a/src/stdio/scanf/scan.c +++ b/src/stdio/scanf/scan.c @@ -449,65 +449,26 @@ int __scanf( break; } - case 'd': { - // read a long int (in base 10 - decimal) from the current input stream - // and store in the corresponding arg as a char by reference - long long int temp; - err = __strto_int( in, 10, NULL, &temp, false ); // base is 10 as for strtol - if (err != 0) return validrets; - if (skip) __scanf_store_i( temp, MODSKIP, args ); - else __scanf_store_i( temp, MOD, args ); - validrets++; - break; - } - - case 'i': { - // read a signed int (base to be defined at read) from the current input stream - // and store in the corresponding arg as a char by reference - long long int temp; - err = __strto_int( in, 0, NULL, &temp, false ); // base is 0 as for strtol - if (err != 0) return validrets; - if (skip) __scanf_store_i( temp, MODSKIP, args ); - else __scanf_store_i( temp, MOD, args ); - validrets++; - break; - } - - case 'u': { - // read a unsigned int (in base 10 - decimal) from the current input stream - // and store in the corresponding arg as a char by reference - long long int temp; - err = __strto_int( in, 10, NULL, &temp, false ); // base is 10 as for strtol - use_unsigned must be false (validated with glibc6.2 behaviour) - if (err != 0) return validrets; - if (skip) __scanf_store_i( temp, MODSKIP, args ); - else __scanf_store_i( temp, MOD, args ); - validrets++; - break; - } - - case 'o': { - // read a unsigned int (in base 8 - octal) from the current input stream - // and store in the corresponding arg as a char by reference - long long int temp; - err = __strto_int( in, 8, NULL, &temp, true ); // base is 8 as for strtol - if (err != 0) return validrets; - if (skip) __scanf_store_i( temp, MODSKIP, args ); - else __scanf_store_i( temp, MOD, args ); - validrets++; - break; - } - + case 'd': + case 'i': + case 'o': + case 'u': case 'x': case 'X': { - // read a unsigned int (in base 16 - hexadecimal) from the current input stream - // and store in the corresponding arg as a char by reference + int f = format[pos]; + int base = (f == 'd' || f == 'u') ? 10 : + (f == 'o') ? 8: + (f == 'x' || f == 'X') ? 16 : 0; + bool use_unsigned = (f == 'o' || f == 'x' || f == 'X'); + long long int temp; - err = __strto_int( in, 16, NULL, &temp, true ); // base is 16 as for strtol - if (err != 0) return validrets; + err = __strto_int(in, base, NULL, &temp, use_unsigned); + if (err == EOF && validrets == 0) return EOF; + if (err != 0) return validrets; if (skip) __scanf_store_i( temp, MODSKIP, args ); else __scanf_store_i( temp, MOD, args ); validrets++; - break; + break; } case 'a': @@ -522,7 +483,8 @@ int __scanf( // and store in the corresponding arg as a char by reference long double temp; err = __strto_fp( in, NULL, NULL, &temp ); - if (err != 0) return validrets; + if (err == EOF && validrets == 0) return EOF; + if (err != 0) return validrets; if (skip) __scanf_store_d( temp, MODSKIP, args ); else __scanf_store_d( temp, MOD, args ); validrets++; diff --git a/src/stdlib/strto_int.c b/src/stdlib/strto_int.c index 9a7f397..b75e43a 100644 --- a/src/stdlib/strto_int.c +++ b/src/stdlib/strto_int.c @@ -16,6 +16,7 @@ int __strto_int(struct __scanf_input *input, int base, long *outl, /* Accept a sign character */ bool negative = false; int sign = __scanf_peek(input); + if(sign == EOF) return EOF; if(sign == '-') negative = true; if(sign == '-' || sign == '+') __scanf_in(input); @@ -39,6 +40,8 @@ int __strto_int(struct __scanf_input *input, int base, long *outl, if(base == 0) base = 8; } + else if(__scanf_peek(input) == EOF) + return EOF; if(base == 0) base = 10; diff --git a/src/stdlib/strtod.c b/src/stdlib/strtod.c index 7c7c786..c7c36ca 100644 --- a/src/stdlib/strtod.c +++ b/src/stdlib/strtod.c @@ -13,7 +13,7 @@ double strtod(char const * restrict ptr, char ** restrict endptr) __scanf_end(&in); if(err != 0) - errno = err; + errno = (err == EOF) ? EINVAL : err; if(err != EINVAL && endptr) *endptr = (char *)in.str; return d; diff --git a/src/stdlib/strtof.c b/src/stdlib/strtof.c index 6264a8b..4459dbe 100644 --- a/src/stdlib/strtof.c +++ b/src/stdlib/strtof.c @@ -13,7 +13,7 @@ float strtof(char const * restrict ptr, char ** restrict endptr) __scanf_end(&in); if(err != 0) - errno = err; + errno = (err == EOF) ? EINVAL : err; if(err != EINVAL && endptr) *endptr = (char *)in.str; return f; diff --git a/src/stdlib/strtol.c b/src/stdlib/strtol.c index 5fafc0a..e584d35 100644 --- a/src/stdlib/strtol.c +++ b/src/stdlib/strtol.c @@ -19,7 +19,7 @@ long int strtol(char const * restrict ptr, char ** restrict endptr, int base) __scanf_end(&in); if(err != 0) - errno = err; + errno = (err == EOF) ? EINVAL : err; if(err != EINVAL && endptr) *endptr = (char *)in.str; return n; diff --git a/src/stdlib/strtold.c b/src/stdlib/strtold.c index 0c58d2b..e4d8f6d 100644 --- a/src/stdlib/strtold.c +++ b/src/stdlib/strtold.c @@ -13,7 +13,7 @@ long double strtold(char const * restrict ptr, char ** restrict endptr) __scanf_end(&in); if(err != 0) - errno = err; + errno = (err == EOF) ? EINVAL : err; if(err != EINVAL && endptr) *endptr = (char *)in.str; return ld; diff --git a/src/stdlib/strtoll.c b/src/stdlib/strtoll.c index 26002ab..6fd19b4 100644 --- a/src/stdlib/strtoll.c +++ b/src/stdlib/strtoll.c @@ -14,7 +14,7 @@ long long int strtoll(char const * restrict ptr, char ** restrict endptr, __scanf_end(&in); if(err != 0) - errno = err; + errno = (err == EOF) ? EINVAL : err; if(err != EINVAL && endptr) *endptr = (char *)in.str; return n; diff --git a/src/stdlib/strtoul.c b/src/stdlib/strtoul.c index 6840c08..b0c7148 100644 --- a/src/stdlib/strtoul.c +++ b/src/stdlib/strtoul.c @@ -14,7 +14,7 @@ unsigned long int strtoul(char const * restrict ptr, char ** restrict endptr, __scanf_end(&in); if(err != 0) - errno = err; + errno = (err == EOF) ? EINVAL : err; if(err != EINVAL && endptr) *endptr = (char *)in.str; return n; diff --git a/src/stdlib/strtoull.c b/src/stdlib/strtoull.c index 2a25290..4061286 100644 --- a/src/stdlib/strtoull.c +++ b/src/stdlib/strtoull.c @@ -14,7 +14,7 @@ unsigned long long int strtoull(char const * restrict ptr, __scanf_end(&in); if(err != 0) - errno = err; + errno = (err == EOF) ? EINVAL : err; if(err != EINVAL && endptr) *endptr = (char *)in.str; return n;