skip parameter

This commit is contained in:
Sylvain PILLOT 2023-02-21 22:36:56 +01:00
parent 00392b42a1
commit af4692fe0b
2 changed files with 124 additions and 29 deletions

View File

@ -8,6 +8,7 @@ extern "C" {
#include <stdio.h>
#include <stdbool.h>
/*
** General utilities for scanf(); we expose them here as we use subfunctions of
@ -26,9 +27,12 @@ struct __scanf_input {
int readmaxlength;
int currentlength;
int skip;
// total number of char read so far in the current call of a XYscanf() function (to return a %n when required)
int readsofar;
bool purgewhitespace;
int buffer;
};

View File

@ -2,6 +2,7 @@
#include <ctype.h>
#include <fxlibc/scanf.h>
#include <fxlibc/stdlib_p.h>
#include <stdbool.h>
void __scanf_start(struct __scanf_input *in)
{
@ -40,6 +41,7 @@ void __scanf_end(struct __scanf_input *in)
enum
{
MODSKIP,
MODSHORTSHORT,
MODSHORT,
MODNORMAL,
@ -48,9 +50,15 @@ enum
MODLONGDOUBLE,
};
void __purge_space( struct __scanf_input * __restrict__ in )
{
while (isspace(__scanf_peek(in))) __scanf_in(in);
}
void __scanf_store_i(int64_t value, int size, va_list *args)
{
if (size==MODSKIP) return;
if(size == MODSHORTSHORT)
*va_arg(*args, int8_t *) = value;
else if(size == MODSHORT)
@ -63,6 +71,8 @@ void __scanf_store_i(int64_t value, int size, va_list *args)
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)
@ -126,7 +136,8 @@ int __scanf(
in->readsofar = 0;
in->readmaxlength = -1;
in->purgewhitespace = false;
in->skip = false;
__scanf_start( in );
@ -137,17 +148,7 @@ int __scanf(
if ( format[i] == ' ' ) // a space in the format string mean that all white-space after the last read and before the next one are to be removed
{
char flush;
for(;;)
{
flush = __scanf_peek( in ); // check if the next character is a whitespace
if (isspace(flush))
{
flush = __scanf_in( in ); // if so, we remove it from the pile and advance
}
else break; // if not, we can move to the following
}
in->readmaxlength = -1;
in->purgewhitespace = true;
i++;
}
else if ( format[i] == '%' ) // read conversion
@ -163,6 +164,12 @@ int __scanf(
switch( format[i] )
{
case '*':
{
in->skip = true;
goto loopagain;
}
case 'h': // we start with MODNORMAL and decrease the length first to MODSHORT and after to MODSHORTSHORT
{
if(mod==MODNORMAL)
@ -225,30 +232,58 @@ int __scanf(
case '%':
{
char c = __scanf_peek( in );
if (c=='%')
{
__scanf_in( in );
ret++;
}
else return ret++; // TODO check if needed
// NOthing to do this is just the character '%'
in->readmaxlength = -1;
in->purgewhitespace = false;
in->skip = false;
break;
}
case 'c':
{
if (in->purgewhitespace==true)
{
__purge_space( in );
in->purgewhitespace=false;
}
// read a char from the current input stream
// and store in the corresponding arg as a char by reference
char *c = (char *) va_arg( *args, char* );
if (in->readmaxlength==-1)
{
*c = __scanf_in( in );
if (in->skip==false) *c = __scanf_in( in );
else
{
char dummy = __scanf_in( in );
}
}
else
{
for(int u = 0; u < in->readmaxlength; u++ )
{
*c = __scanf_in( in );
c++;
if (in->skip==false)
{
*c = __scanf_in( in );
c++;
}
else
{
char dummy = __scanf_in( in );
}
}
}
in->readmaxlength=-1;
in->skip = false;
ret++;
break;
@ -258,11 +293,14 @@ int __scanf(
{
// read a long int (in base 10 - decimal) from the current input stream
// and store in the corresponding arg as a char by reference
in->purgewhitespace = false;
long long int temp;
err = __strto_int( in, 10, NULL, &temp, false ); // base is 10 as for strtol
if (err == 0)
{
__scanf_store_i( temp, mod, args );
if (in->skip==false) __scanf_store_i( temp, mod, args );
else __scanf_store_i( temp, MODSKIP, args );
in->skip = false;
mod = MODNORMAL;
ret++;
}
@ -273,12 +311,14 @@ int __scanf(
{
// read a long int (in base determined by the first character) from the current input stream
// and store in the corresponding arg as a char by reference
in->purgewhitespace = false;
long long int temp;
err = __strto_int( in, 0, NULL, &temp, false ); // base is 0 as for strtol
if (err == 0)
{
__scanf_store_i( temp, mod, args );
if (in->skip==false) __scanf_store_i( temp, mod, args );
else __scanf_store_i( temp, MODSKIP, args );
in->skip = false;
mod = MODNORMAL;
ret++;
}
@ -290,11 +330,14 @@ int __scanf(
{
// read a unsigned long int (in base 10 - decimal) from the current input stream
// and store in the corresponding arg as a char by reference
in->purgewhitespace = false;
long long int temp;
err = __strto_int( in, 10, NULL, &temp, true ); // base is 10 as for strtol
if (err == 0)
{
__scanf_store_i( temp, mod, args );
if (in->skip==false) __scanf_store_i( temp, mod, args );
else __scanf_store_i( temp, MODSKIP, args );
in->skip = false;
mod = MODNORMAL;
ret++;
}
@ -305,11 +348,14 @@ int __scanf(
{
// read a unsigned long int (in base 8 - octal) from the current input stream
// and store in the corresponding arg as a char by reference
in->purgewhitespace = false;
long long int temp;
err = __strto_int( in, 8, NULL, &temp, true ); // base is 8 as for strtol
if (err == 0)
{
__scanf_store_i( temp, mod, args );
if (in->skip==false) __scanf_store_i( temp, mod, args );
else __scanf_store_i( temp, MODSKIP, args );
in->skip = false;
mod = MODNORMAL;
ret++;
}
@ -321,11 +367,14 @@ int __scanf(
{
// read a unsigned long int (in base 16 - hexadecimal) from the current input stream
// and store in the corresponding arg as a char by reference
in->purgewhitespace = false;
long long int temp;
err = __strto_int( in, 16, NULL, &temp, true ); // base is 16 as for strtol
if (err == 0)
{
__scanf_store_i( temp, mod, args );
if (in->skip==false) __scanf_store_i( temp, mod, args );
else __scanf_store_i( temp, MODSKIP, args );
in->skip = false;
mod = MODNORMAL;
ret++;
}
@ -341,11 +390,14 @@ int __scanf(
case 'g':
case 'G':
{
in->purgewhitespace = false;
long double temp;
err = __strto_fp( in, NULL, NULL, &temp );
if (err == 0)
{
__scanf_store_d( temp, mod, args );
if (in->skip==false) __scanf_store_d( temp, mod, args );
else __scanf_store_d( temp, MODSKIP, args );
in->skip = false;
mod = MODNORMAL;
ret++;
}
@ -354,6 +406,9 @@ int __scanf(
case 's':
{
__purge_space( in );
in->purgewhitespace=false;
// read a serie of non whitespace char from the current input stream
// and store in the corresponding arg as a char by reference
char *c = (char *) va_arg( *args, char* );
@ -365,8 +420,15 @@ int __scanf(
temp = __scanf_peek( in );
if (!isspace(temp) && temp != EOF)
{
*c = __scanf_in( in );
c++;
if (in->skip == false )
{
*c = __scanf_in( in );
c++;
}
else
{
char dummy = __scanf_in( in );
}
}
else break;
}
@ -379,8 +441,15 @@ int __scanf(
temp = __scanf_peek( in );
if (!isspace(temp) && temp != EOF)
{
*c = __scanf_in( in );
c++;
if (in->skip == false )
{
*c = __scanf_in( in );
c++;
}
else
{
char dummy = __scanf_in( in );
}
}
else break;
}
@ -393,6 +462,7 @@ int __scanf(
case 'n':
{
in->purgewhitespace = false;
// rreturn the number of characters read so far
int *n = (int *) va_arg( *args, int* );
*n = in->readsofar;
@ -403,15 +473,36 @@ int __scanf(
case 'p':
{
void *p = (void *) va_arg( *args, void** ); // get the adress of the target pointer (void**)
err = __strto_int( in, 0, p, NULL, true );
/* FORMER CODE
void *p = (void *) va_arg( *args, void** ); // get the adress of the target pointer (void**)
err = __strto_int( in, 0, p, NULL, true );
if (err == 0) ret++;
*/
in->purgewhitespace = false;
long int dummy;
err = __strto_int( in, 0, &dummy, NULL, true );
if (in->skip == false)
{
void *p = (void *) va_arg( *args, void** ); // get the adress of the target pointer (void**)
p=(void*) dummy;
}
if (err == 0) ret++;
in->skip = false;
break;
}
}
}
else i++;
else
{
if (format[i] == __scanf_in( in )) i++;
else err=1;
}
if (err!=0) break; // an error occured somewhere whiloe parsing the values
}