stdio: make all scanf tests pass

The tests are still far from exhaustive but that's a good start.
This commit is contained in:
Lephenixnoir 2024-01-14 17:30:30 +01:00
parent b61cc096d9
commit 2215b3c267
No known key found for this signature in database
GPG key ID: 1BBA026E13FC0495
9 changed files with 26 additions and 61 deletions

View file

@ -449,60 +449,21 @@ 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
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 );
@ -522,6 +483,7 @@ 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 == 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 );

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;