From 55ae7df318183316805bdf1cdf794913abeb2a96 Mon Sep 17 00:00:00 2001 From: Lephenixnoir Date: Sun, 14 Jan 2024 20:18:24 +0100 Subject: [PATCH] stdio: simplify output size management in scanf --- src/stdio/scanf/scan.c | 174 ++++++++++++++--------------------------- src/stdio/stdio_p.h | 13 ++- 2 files changed, 65 insertions(+), 122 deletions(-) diff --git a/src/stdio/scanf/scan.c b/src/stdio/scanf/scan.c index f6684ca..2e702d5 100644 --- a/src/stdio/scanf/scan.c +++ b/src/stdio/scanf/scan.c @@ -37,21 +37,6 @@ void __scanf_end(struct __scanf_input *in) in->str--; } - -enum -{ - MODSKIP, - MODCHAR, - MODSHORT, - MODNORMAL, - MODLONG, - MODLONGLONG, - MODLONGDOUBLE, - MODINTMAXT, - MODSIZET, - MODPTRDIFFT, -}; - void __purge_space( struct __scanf_input * __restrict__ in ) { while (isspace(__scanf_peek(in))) __scanf_in(in); @@ -59,34 +44,24 @@ void __purge_space( struct __scanf_input * __restrict__ in ) void __scanf_store_i(int64_t value, int size, va_list *args) { - if(size == MODSKIP) return; - - if(size == MODCHAR) + if(size == 1) *va_arg(*args, int8_t *) = value; - else if(size == MODSHORT) + else if(size == 2) *va_arg(*args, int16_t *) = value; - else if(size == MODLONGLONG) + else if(size == 4) + *va_arg(*args, int32_t *) = value; + else if(size == 8) *va_arg(*args, int64_t *) = value; - else if(size == MODINTMAXT) - *va_arg(*args, intmax_t *) = value; - else if(size == MODSIZET) - *va_arg(*args, size_t *) = value; - else if(size == MODPTRDIFFT) - *va_arg(*args, ptrdiff_t *) = value; - else - *va_arg(*args, int *) = value; } void __scanf_store_d(long double value, int size, va_list *args) { - if (size==MODSKIP) return; - - if(size == MODLONG) - *va_arg(*args, double *) = value; - else if(size == MODLONGDOUBLE) - *va_arg(*args, long double *) = value; - else + if(size == sizeof(float)) *va_arg(*args, float *) = value; + else if(size == sizeof(double)) + *va_arg(*args, double *) = value; + else if(size == sizeof(long double)) + *va_arg(*args, long double *) = value; } /* STATUS OF __scanf DEVELOPMENT */ @@ -239,11 +214,9 @@ int __scanf( { bool skip = false; - - int MOD = MODNORMAL; + int MOD = sizeof(int); - in->readsofar = 0; // we haven't started to read char from the input stream - in->readmaxlength = -1; // no specific maximum length to read is defined yet + 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 @@ -255,9 +228,8 @@ int __scanf( // TODO: No __scanf_end() in any of the "return validrets"!! while( format[pos] != 0 ) { - in->readmaxlength = -1; user_length = 0; - MOD = MODNORMAL; + MOD = sizeof(int); skip = false; __allow_all_set(); @@ -268,7 +240,9 @@ int __scanf( // we will have to manage a given format else if( format[pos] == '%' ) { - in->readmaxlength = INT_MAX; + int readmaxlength = INT_MAX; + char size_letter = 0; + // main loop loopagain: @@ -282,7 +256,7 @@ int __scanf( int currentlength = 0; // we need to assign the read char to the corresponding pointer char *c = skip ? NULL : va_arg(*args, char *); - for(unsigned int u=0; ureadmaxlength; u++) { + for(int u=0; ureadsofar; + case 'n': + *va_arg(*args, int *) = in->bytes_read; break; - } // we are expecting the char '%' to be in the input stream, if not err and return case '%': { @@ -314,69 +287,36 @@ int __scanf( } // the next read, even if valid, will not be stored - case '*': { + case '*': skip = true; goto loopagain; - break; - } - case 'h': { - if (MOD==MODNORMAL || MOD==MODSHORT) { - MOD--; - goto loopagain; - } - else return validrets; // we cannot have %hhh format modifier --> err - break; - } - - case 'l': { - if (MOD==MODNORMAL || MOD==MODLONG) { - MOD++; - goto loopagain; - } - else return validrets; // we cannot have %ll format modifier --> err - break; - } - - case 'L': { - if (MOD==MODNORMAL) { - MOD=MODLONGDOUBLE; - goto loopagain; - } - else return validrets; // we cannot have %LL format modifier --> err - break; - } - - case 'j': { - if (MOD==MODNORMAL) { - MOD=MODINTMAXT; - goto loopagain; - } - else return validrets; // we cannot have %LL format modifier --> err - break; - } - - case 'z': { - if (MOD==MODNORMAL) { - MOD=MODSIZET; - goto loopagain; - } - else return validrets; // we cannot have %LL format modifier --> err - break; - } - - case 't': { - if (MOD==MODNORMAL) { - MOD=MODPTRDIFFT; - goto loopagain; - } - else return validrets; // we cannot have %LL format modifier --> err - break; - } + case 'h': + MOD = (size_letter == 'h') ? sizeof(char) : sizeof(short); + size_letter = 'h'; + goto loopagain; + case 'l': + MOD = (size_letter == 'l') ? sizeof(long long) : sizeof(long); + /* FP conversions will adjust to sizeof(double) later */ + size_letter = 'l'; + goto loopagain; + case 'L': + MOD = sizeof(long double); + size_letter = 'L'; + goto loopagain; + case 'j': + MOD = sizeof(intmax_t); + goto loopagain; + case 'z': + MOD = sizeof(size_t); + goto loopagain; + case 't': + MOD = sizeof(ptrdiff_t); + goto loopagain; case '0' ... '9': { user_length = user_length * 10 + (int) ( format[pos] - '0' ); - in->readmaxlength = user_length; + readmaxlength = user_length; goto loopagain; break; } @@ -395,10 +335,10 @@ int __scanf( long long int temp; err = __strto_int(in, base, NULL, &temp, use_unsigned, - in->readmaxlength); + readmaxlength); if (err == EOF && validrets == 0) return EOF; if (err != 0) return validrets; - if (skip) __scanf_store_i( temp, MODSKIP, args ); + if (skip) __scanf_store_i( temp, 0, args ); else __scanf_store_i( temp, MOD, args ); validrets++; break; @@ -411,15 +351,21 @@ int __scanf( case 'f': case 'F': case 'g': - case 'G': { + case 'G': { + /* Adjust interpretation of no size / 'l' size */ + if(size_letter == 0) + MOD = sizeof(float); + if(size_letter == 'l') + MOD = sizeof(double); + // 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, - in->readmaxlength); + readmaxlength); if (err == EOF && validrets == 0) return EOF; if (err != 0) return validrets; - if (skip) __scanf_store_d( temp, MODSKIP, args ); + if (skip) __scanf_store_d( temp, 0, args ); else __scanf_store_d( temp, MOD, args ); validrets++; break; @@ -430,10 +376,10 @@ int __scanf( if (!skip) { void *p = (void *) va_arg( *args, void** ); // get the adress of the target pointer (void**) err = __strto_int( in, 0, p, NULL, true, - in->readmaxlength); + readmaxlength); } else err = __strto_int( in, 0, &temp, NULL, true, - in->readmaxlength); + readmaxlength); if (err == 0) validrets++; else return validrets; skip = false; @@ -441,11 +387,11 @@ int __scanf( } case 'c': { - if(in->readmaxlength == INT_MAX) - in->readmaxlength = 1; + if(readmaxlength == INT_MAX) + readmaxlength = 1; char *c = skip ? NULL : va_arg(*args, char *); - for(unsigned int u = 0; u < in->readmaxlength; u++) { + for(int u = 0; u < readmaxlength; u++) { int temp = __scanf_in(in); if(temp==EOF) return EOF; else if(c) *c++ = temp; @@ -460,7 +406,7 @@ int __scanf( __purge_space(in); char *c = skip ? NULL : va_arg(*args, char *); - for(unsigned int u = 0; u < in->readmaxlength; u++) { + for(int u = 0; u < readmaxlength; u++) { temp = __scanf_peek(in); if(temp==EOF && curstrlength==0) return validrets; if(isspace(temp) || ((temp==EOF && curstrlength!=0))) { diff --git a/src/stdio/stdio_p.h b/src/stdio/stdio_p.h index 8dae131..e6ed65b 100644 --- a/src/stdio/stdio_p.h +++ b/src/stdio/stdio_p.h @@ -18,15 +18,12 @@ struct __scanf_input { char const * __restrict__ str; FILE *fp; - // max char to read from the input stream as per user length modifier - unsigned int readmaxlength; - - // total number of char read so far in the current call of a XYscanf() function (to return a %n when required) - int readsofar; - + /* Single-character lookahead buffer */ int buffer; -}; + /* Total numbers of bytes read in a scall to *scanf() */ + int bytes_read; +}; /* Generic formatted scaning. */ extern int __scanf( @@ -46,7 +43,7 @@ static inline int __scanf_in(struct __scanf_input *__in) { int c = __in->buffer; __in->buffer = __scanf_fetch(__in); - __in->readsofar++; + __in->bytes_read++; return c; }