stdio: deduplicate scanf cases and remove most gotos

This commit is contained in:
Lephenixnoir 2024-01-14 20:07:24 +01:00
parent b11c059c0f
commit 69eadb67d2
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
1 changed files with 65 additions and 192 deletions

View File

@ -161,9 +161,9 @@ void __define_set_range( char c1, char c2, bool value )
}
/* return true if the char is in the allowed set or false otherwise */
bool __is_allowed( const unsigned char c )
bool __is_allowed(int c)
{
return __asciiallowed[ c ];
return (c != EOF) && __asciiallowed[c];
}
@ -200,37 +200,34 @@ int __scanset(char const * __restrict__ format, int *pos )
}
}
// start of format analysis loop
loopset:
// we find a '-' so need to check if we are considering a range or the char '-' only
if (format[*pos]=='-') {
// the char '-' is included in the allowed set
if (format[*pos+1]==']') {
__asciiallowed[ '-' ] = !__neg; // if set in very final position before']', this is the char '-' only
(*pos)++;
// we have now finished the reading of the set cause the following char is ']'
return 0;
while(1) {
// we find a '-' so need to check if we are considering a range or the char '-' only
if (format[*pos]=='-') {
// the char '-' is included in the allowed set
if (format[*pos+1]==']') {
__asciiallowed[ '-' ] = !__neg; // if set in very final position before']', this is the char '-' only
(*pos)++;
// we have now finished the reading of the set cause the following char is ']'
return 0;
}
// the char '-' indicates a range of char to be included into the set
else {
(*pos)++;
__eor = format[*pos];
__define_set_range( __sor, __eor, !__neg );
}
}
// the char '-' indicates a range of char to be included into the set
// we find the char ']' so it means we reach the end of this set
else if (format[*pos]==']') return 0;
// if we reach the '\0' we have a syntax problem
else if (format[*pos]=='\0') return -1;
// we are considering one particular char and prepare for a potential range if we find the char '-' later on
else {
__sor = format[*pos];
__asciiallowed[ __sor ] = !__neg;
(*pos)++;
__eor = format[*pos];
__define_set_range( __sor, __eor, !__neg );
goto loopset;
}
}
// we find the char ']' so it means we reach the end of this set
else if (format[*pos]==']') return 0;
// if we reach the '\0' we have a syntax problem
else if (format[*pos]=='\0') return -1;
// we are considering one particular char and prepare for a potential range if we find the char '-' later on
else {
__sor = format[*pos];
__asciiallowed[ __sor ] = !__neg;
(*pos)++;
goto loopset;
}
}
@ -255,6 +252,8 @@ int __scanf(
__scanf_start( in );
// TODO: No __scanf_end() in any of the "return validrets"!!
while( format[pos] != 0 ) {
in->readmaxlength = -1;
user_length = 0;
@ -278,83 +277,26 @@ int __scanf(
switch( format[pos] ) {
// we need to decrypt the corresponding scanf set of character
case '[': {
char temp;
err = __scanset( format, &pos );
if (err!=0) return validrets;
int currentlength = 0;
// we need to assign the read char to the corresponding pointer
if (!skip) {
char *c = (char *) va_arg( *args, char* );
if (in->readmaxlength==INT_MAX) {
for(;;) {
temp = __scanf_peek( in );
if (temp==EOF) return EOF;
else if (__is_allowed( temp )) {
*c++ = __scanf_in( in );
currentlength++;
}
else {
if (currentlength>0) {
*c = '\0';
validrets++;
goto exitset;
}
else return validrets;
}
}
}
else {
for(unsigned int u=0; u<in->readmaxlength; u++) {
temp = __scanf_peek( in );
if (temp==EOF) return EOF;
else if (__is_allowed( temp )) {
*c++ = __scanf_in( in );
currentlength++;
}
else {
if (currentlength>0) {
*c = '\0';
validrets++;
goto exitset;
}
else return validrets;
}
}
if (currentlength>0) {
*c = '\0';
validrets++;
goto exitset;
}
else return validrets;
char *c = skip ? NULL : va_arg(*args, char *);
for(unsigned int u=0; u<in->readmaxlength; u++) {
int temp = __scanf_peek(in);
if(__is_allowed(temp)) {
__scanf_in(in);
if(c) *c++ = temp;
currentlength++;
}
else if(temp==EOF && !currentlength && !validrets)
return EOF;
else break;
}
else
{
if (in->readmaxlength==INT_MAX) {
for(;;) {
temp = __scanf_peek( in );
if (temp==EOF) return EOF;
else if (__is_allowed( temp )) {
__scanf_in( in );
currentlength++;
}
else if (currentlength>0) goto exitset;
else return validrets;
}
}
else {
for(unsigned int u=0; u<in->readmaxlength; u++) {
temp = __scanf_peek( in );
if (temp==EOF) return EOF;
else if (__is_allowed( temp )) __scanf_in( in );
else if (currentlength>0) goto exitset;
else return validrets;
}
}
}
exitset:
if(!currentlength)
return validrets;
*c = '\0';
validrets += !skip;
break;
}
@ -499,111 +441,42 @@ int __scanf(
}
case 'c': {
int temp;
if (!skip) {
char *c = (char *) va_arg( *args, char* );
if (in->readmaxlength==INT_MAX) {
temp = __scanf_peek( in );
if (temp==EOF) return EOF;
else *c = __scanf_in( in );
}
else {
for( unsigned int u = 0; u < in->readmaxlength; u++ ) {
temp = __scanf_peek( in );
if (temp==EOF) return EOF;
else *c++ = __scanf_in( in );
}
}
}
else {
if (in->readmaxlength==INT_MAX) {
temp = __scanf_peek( in );
if (temp==EOF) return EOF;
else {
__scanf_in( in );
goto endcharskip;
}
}
else {
for( unsigned int u = 0; u < in->readmaxlength; u++ ) {
temp = __scanf_peek( in );
if (temp==EOF) return EOF;
else __scanf_in( in );
}
goto endcharskip;
}
}
validrets++;
if(in->readmaxlength == INT_MAX)
in->readmaxlength = 1;
char *c = skip ? NULL : va_arg(*args, char *);
endcharskip:
for(unsigned int u = 0; u < in->readmaxlength; u++) {
int temp = __scanf_in(in);
if(temp==EOF) return EOF;
else if(c) *c++ = temp;
}
validrets += !skip;
break;
}
case 's': {
char temp;
int curstrlength = 0;
__purge_space( in );
if (!skip) {
char *c = (char *) va_arg( *args, char* );
if (in->readmaxlength==INT_MAX) {
loopstring:
temp = __scanf_peek( in );
if (temp==EOF && curstrlength==0) return validrets;
if (isspace(temp) || ( (temp==EOF && curstrlength!=0) )) {
*c = 0;
goto loopstringend;
}
else {
*c++ = __scanf_in( in );
curstrlength++;
goto loopstring;
__purge_space(in);
char *c = skip ? NULL : va_arg(*args, char *);
for(unsigned int u = 0; u < in->readmaxlength; 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 {
for( unsigned int u = 0; u < in->readmaxlength; u++ ) {
temp = __scanf_peek( in );
if (temp==EOF && curstrlength==0) return validrets;
if (isspace(temp) || ( (temp==EOF && curstrlength!=0) )) {
*c = 0;
goto loopstringend;
}
else {
*c++ = __scanf_in( in );
curstrlength++;
}
}
int temp = __scanf_in( in );
if(c)
*c++ = temp;
curstrlength++;
}
}
else {
if (in->readmaxlength==INT_MAX) {
loopstringskip:
temp = __scanf_peek( in );
if (temp==EOF && curstrlength==0) return validrets;
if (isspace(temp) || ( (temp==EOF && curstrlength!=0) )) goto loopstringendskip;
else {
__scanf_in( in );
curstrlength++;
goto loopstringskip;
}
}
else {
for( unsigned int u = 0; u < in->readmaxlength; u++ ) {
temp = __scanf_peek( in );
if (temp==EOF && curstrlength==0) return validrets;
if (isspace(temp) || ( (temp==EOF && curstrlength!=0) )) goto loopstringendskip;
else {
__scanf_in( in );
curstrlength++;
}
}
}
}
loopstringend:
validrets++;
loopstringendskip:
break;
}
}