From 527c2e48fc72368f48cfba642e747c4ffe386715 Mon Sep 17 00:00:00 2001 From: Lephenixnoir Date: Sun, 14 Jan 2024 21:27:48 +0100 Subject: [PATCH] stdio: more syntaxic refactoring of scanf --- src/stdio/scanf/scan.c | 274 +++++++++++++++++++---------------------- 1 file changed, 130 insertions(+), 144 deletions(-) diff --git a/src/stdio/scanf/scan.c b/src/stdio/scanf/scan.c index 0bf137d..e719fe8 100644 --- a/src/stdio/scanf/scan.c +++ b/src/stdio/scanf/scan.c @@ -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; ubytes_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; + } } }