mirror of
https://git.planet-casio.com/Vhex-Kernel-Core/fxlibc.git
synced 2024-12-28 04:23:38 +01:00
stdio: more syntaxic refactoring of scanf
This commit is contained in:
parent
9f6e0c8039
commit
527c2e48fc
1 changed files with 130 additions and 144 deletions
|
@ -273,169 +273,155 @@ int __scanf(
|
|||
char const * __restrict__ format,
|
||||
va_list *args)
|
||||
{
|
||||
|
||||
in->bytes_read = 0; // we haven't started to read char from the input stream
|
||||
|
||||
int validrets = 0; // to be incremented each time we successfully read and store an input as per the format
|
||||
int err = 0; // err control on __strto_xx( ) functions
|
||||
int pos = 0; // current pos in the format string
|
||||
/* Number of successful assignments */
|
||||
int validrets = 0;
|
||||
|
||||
__scanf_start( in );
|
||||
|
||||
// TODO: No __scanf_end() in any of the "return validrets"!!
|
||||
|
||||
for(; format[pos]; pos++) {
|
||||
for(int pos = 0; format[pos]; pos++) {
|
||||
if(format[pos] == ' ') {
|
||||
__purge_space(in);
|
||||
continue;
|
||||
}
|
||||
else if(format[pos] != '%') {
|
||||
// if the next char of the stream is corresponding, we validate the read and go to the following char
|
||||
if(format[pos] == __scanf_peek( in )) {
|
||||
__scanf_in( in );
|
||||
pos++;
|
||||
continue;
|
||||
}
|
||||
else return validrets; // else we return the number of valid read
|
||||
}
|
||||
else if(format[pos + 1] == '%') {
|
||||
if(__scanf_peek(in) != '%') return validrets;
|
||||
else __scanf_in( in );
|
||||
pos++;
|
||||
else if(format[pos] != '%' || format[pos + 1] == '%') {
|
||||
/* Expect this specific character */
|
||||
if(__scanf_peek(in) != format[pos])
|
||||
return validrets;
|
||||
__scanf_in(in);
|
||||
pos += (format[pos] == '%');
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Perform a conversion */
|
||||
else {
|
||||
struct scanf_format opt;
|
||||
int spec = parse_fmt(format, &pos, &opt);
|
||||
if(spec == 0)
|
||||
struct scanf_format opt;
|
||||
int spec = parse_fmt(format, &pos, &opt);
|
||||
if(spec == 0)
|
||||
return validrets;
|
||||
|
||||
switch(spec) {
|
||||
// we need to decrypt the corresponding scanf set of character
|
||||
case '[': {
|
||||
int currentlength = 0;
|
||||
// we need to assign the read char to the corresponding pointer
|
||||
char *c = opt.skip ? NULL : va_arg(*args, char *);
|
||||
for(int u=0; u<opt.field_width; u++) {
|
||||
int temp = __scanf_peek(in);
|
||||
if(bracket_set_test(opt.bracket_set, temp)) {
|
||||
__scanf_in(in);
|
||||
if(c) *c++ = temp;
|
||||
currentlength++;
|
||||
}
|
||||
else if(temp==EOF && !currentlength && !validrets)
|
||||
return EOF;
|
||||
else break;
|
||||
}
|
||||
if(!currentlength)
|
||||
return validrets;
|
||||
*c = '\0';
|
||||
validrets += !opt.skip;
|
||||
break;
|
||||
}
|
||||
|
||||
switch(spec) {
|
||||
// we need to decrypt the corresponding scanf set of character
|
||||
case '[': {
|
||||
int currentlength = 0;
|
||||
// we need to assign the read char to the corresponding pointer
|
||||
char *c = opt.skip ? NULL : va_arg(*args, char *);
|
||||
for(int u=0; u<opt.field_width; u++) {
|
||||
int temp = __scanf_peek(in);
|
||||
if(bracket_set_test(opt.bracket_set, temp)) {
|
||||
__scanf_in(in);
|
||||
if(c) *c++ = temp;
|
||||
currentlength++;
|
||||
// return the number of char read so far (cannot be skipped %*n is not valid)
|
||||
case 'n':
|
||||
*va_arg(*args, int *) = in->bytes_read;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
case 'i':
|
||||
case 'o':
|
||||
case 'u':
|
||||
case 'x':
|
||||
case 'X': {
|
||||
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;
|
||||
int err = __strto_int(in, base, NULL, &temp, use_unsigned,
|
||||
opt.field_width);
|
||||
if(err == EOF && validrets == 0) return EOF;
|
||||
if(err) return validrets;
|
||||
if(!opt.skip)
|
||||
__scanf_store_i(temp, opt.size, args);
|
||||
validrets++;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'a':
|
||||
case 'A':
|
||||
case 'e':
|
||||
case 'E':
|
||||
case 'f':
|
||||
case 'F':
|
||||
case 'g':
|
||||
case 'G': {
|
||||
// read a double from the current input stream
|
||||
// and store in the corresponding arg as a char by reference
|
||||
long double temp;
|
||||
int err = __strto_fp(in, NULL, NULL, &temp, opt.field_width);
|
||||
if(err == EOF && validrets == 0) return EOF;
|
||||
if(err) return validrets;
|
||||
if(!opt.skip)
|
||||
__scanf_store_d(temp, opt.size, args);
|
||||
validrets++;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'p': {
|
||||
long int temp;
|
||||
int err = 0;
|
||||
if(!opt.skip) {
|
||||
void *p = va_arg(*args, void *);
|
||||
err = __strto_int(in, 0, p, NULL, true, opt.field_width);
|
||||
validrets += (err == 0);
|
||||
}
|
||||
else err = __strto_int(in, 0, &temp, NULL, true, opt.field_width);
|
||||
if(err) return validrets;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'c': {
|
||||
char *c = opt.skip ? NULL : va_arg(*args, char *);
|
||||
|
||||
for(int u = 0; u < opt.field_width; u++) {
|
||||
int temp = __scanf_in(in);
|
||||
if(temp==EOF) return EOF;
|
||||
else if(c) *c++ = temp;
|
||||
}
|
||||
validrets += !opt.skip;
|
||||
break;
|
||||
}
|
||||
|
||||
case 's': {
|
||||
char temp;
|
||||
int curstrlength = 0;
|
||||
__purge_space(in);
|
||||
|
||||
char *c = opt.skip ? NULL : va_arg(*args, char *);
|
||||
for(int u = 0; u < opt.field_width; u++) {
|
||||
temp = __scanf_peek(in);
|
||||
if(temp==EOF && curstrlength==0) return validrets;
|
||||
if(isspace(temp) || ((temp==EOF && curstrlength!=0))) {
|
||||
if(c) {
|
||||
*c = 0;
|
||||
validrets++;
|
||||
}
|
||||
else if(temp==EOF && !currentlength && !validrets)
|
||||
return EOF;
|
||||
else break;
|
||||
break;
|
||||
}
|
||||
if(!currentlength)
|
||||
return validrets;
|
||||
*c = '\0';
|
||||
validrets += !opt.skip;
|
||||
break;
|
||||
}
|
||||
|
||||
// return the number of char read so far (cannot be skipped %*n is not valid)
|
||||
case 'n':
|
||||
*va_arg(*args, int *) = in->bytes_read;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
case 'i':
|
||||
case 'o':
|
||||
case 'u':
|
||||
case 'x':
|
||||
case 'X': {
|
||||
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, base, NULL, &temp, use_unsigned,
|
||||
opt.field_width);
|
||||
if (err == EOF && validrets == 0) return EOF;
|
||||
if (err != 0) return validrets;
|
||||
if(!opt.skip)
|
||||
__scanf_store_i( temp, opt.size, args );
|
||||
validrets++;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'a':
|
||||
case 'A':
|
||||
case 'e':
|
||||
case 'E':
|
||||
case 'f':
|
||||
case 'F':
|
||||
case 'g':
|
||||
case 'G': {
|
||||
// read a double from the current input stream
|
||||
// and store in the corresponding arg as a char by reference
|
||||
long double temp;
|
||||
err = __strto_fp( in, NULL, NULL, &temp,
|
||||
opt.field_width);
|
||||
if (err == EOF && validrets == 0) return EOF;
|
||||
if (err != 0) return validrets;
|
||||
if(!opt.skip)
|
||||
__scanf_store_d( temp, opt.size, args );
|
||||
validrets++;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'p': {
|
||||
long int temp;
|
||||
if (!opt.skip) {
|
||||
void *p = (void *) va_arg( *args, void** ); // get the adress of the target pointer (void**)
|
||||
err = __strto_int( in, 0, p, NULL, true,
|
||||
opt.field_width);
|
||||
}
|
||||
else err = __strto_int( in, 0, &temp, NULL, true,
|
||||
opt.field_width);
|
||||
if (err == 0) validrets++;
|
||||
else return validrets;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'c': {
|
||||
char *c = opt.skip ? NULL : va_arg(*args, char *);
|
||||
|
||||
for(int u = 0; u < opt.field_width; u++) {
|
||||
else {
|
||||
int temp = __scanf_in(in);
|
||||
if(temp==EOF) return EOF;
|
||||
else if(c) *c++ = temp;
|
||||
if(c)
|
||||
*c++ = temp;
|
||||
curstrlength++;
|
||||
}
|
||||
validrets += !opt.skip;
|
||||
break;
|
||||
}
|
||||
|
||||
case 's': {
|
||||
char temp;
|
||||
int curstrlength = 0;
|
||||
__purge_space(in);
|
||||
|
||||
char *c = opt.skip ? NULL : va_arg(*args, char *);
|
||||
for(int u = 0; u < opt.field_width; u++) {
|
||||
temp = __scanf_peek(in);
|
||||
if(temp==EOF && curstrlength==0) return validrets;
|
||||
if(isspace(temp) || ((temp==EOF && curstrlength!=0))) {
|
||||
if(c) {
|
||||
*c = 0;
|
||||
validrets++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else {
|
||||
int temp = __scanf_in( in );
|
||||
if(c)
|
||||
*c++ = temp;
|
||||
curstrlength++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue