forked from Vhex-Kernel-Core/fxlibc
Compare commits
4 Commits
00392b42a1
...
9e99da0dff
Author | SHA1 | Date |
---|---|---|
Sylvain PILLOT | 9e99da0dff | |
Sylvain PILLOT | da1d26e6cc | |
Sylvain PILLOT | 7b7b7a1ed1 | |
Sylvain PILLOT | af4692fe0b |
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
@ -9,7 +10,7 @@ void __scanf_start(struct __scanf_input *in)
|
|||
if(in->fp)
|
||||
in->buffer = fgetc(in->fp);
|
||||
else {
|
||||
in->buffer = *in->str;
|
||||
in->buffer = (*in->str ? *in->str : EOF);
|
||||
in->str += (in->buffer != 0);
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -111,102 +121,135 @@ void __scanf_store_d(long double value, int size, va_list *args)
|
|||
/* p * mathc a pointer * -- * -- * -- * OK * -- * -- * -- * -- * -- * -- */
|
||||
/*************************************************************************************************************/
|
||||
|
||||
#define DEBUG 0
|
||||
#if DEBUG
|
||||
|
||||
#include <gint/gint.h>
|
||||
void DBGPrint( char * const str)
|
||||
{
|
||||
FILE* f= fopen( "BDG_Out.txt", "a" );
|
||||
fprintf( f, "%s\n", str );
|
||||
fclose( f );
|
||||
}
|
||||
|
||||
void DBG( char * const str )
|
||||
{
|
||||
gint_world_switch( GINT_CALL( DBGPrint, str ) );
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void DBG( char * const str )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
int __scanf(
|
||||
struct __scanf_input * __restrict__ in,
|
||||
char const * __restrict__ format,
|
||||
va_list *args)
|
||||
{
|
||||
int i=0;
|
||||
int ret = 0;
|
||||
int err = 0;
|
||||
|
||||
int mod = MODNORMAL;
|
||||
int length = 0;
|
||||
bool SKIP = false;
|
||||
int MOD = MODNORMAL;
|
||||
|
||||
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->readsofar = 0;
|
||||
in->readmaxlength = -1;
|
||||
int VALIDRETS = 0; // to be incremented each time we successfully read and store an input as per the format
|
||||
int ERROR = 0; // ERROR control on __strto_xx( ) functions
|
||||
|
||||
int user_length = 0;
|
||||
|
||||
int pos = 0;
|
||||
|
||||
__scanf_start( in );
|
||||
|
||||
DBG( "---------\n" );
|
||||
DBG( "In Scanf " );
|
||||
|
||||
while( format[i]!=0 )
|
||||
while( format[pos] != 0 )
|
||||
{
|
||||
|
||||
DBG( "Parsing ..." );
|
||||
|
||||
in->readmaxlength = -1;
|
||||
user_length = 0;
|
||||
MOD = MODNORMAL;
|
||||
SKIP = false;
|
||||
|
||||
|
||||
if( format[pos] == '%' ) // we will have to manage a given format
|
||||
{
|
||||
DBG( "'%' read");
|
||||
|
||||
|
||||
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;
|
||||
i++;
|
||||
}
|
||||
else if ( format[i] == '%' ) // read conversion
|
||||
{
|
||||
|
||||
mod = MODNORMAL;
|
||||
length = 0;
|
||||
in->readmaxlength=-1;
|
||||
|
||||
loopagain:
|
||||
|
||||
i++;
|
||||
switch( format[i] )
|
||||
DBG( "Looping ..." );
|
||||
|
||||
pos++;
|
||||
|
||||
switch( format[pos] )
|
||||
{
|
||||
|
||||
case 'h': // we start with MODNORMAL and decrease the length first to MODSHORT and after to MODSHORTSHORT
|
||||
case 'n': // return the number of char read so far (cannot be skipped %*n is not valid)
|
||||
{
|
||||
if(mod==MODNORMAL)
|
||||
{
|
||||
mod=MODSHORT;
|
||||
goto loopagain;
|
||||
}
|
||||
else if(mod==MODSHORT)
|
||||
{
|
||||
mod=MODSHORTSHORT;
|
||||
goto loopagain;
|
||||
}
|
||||
else
|
||||
{
|
||||
mod=MODNORMAL;
|
||||
break; // we cannot have %hhh
|
||||
}
|
||||
DBG( "'n' read");
|
||||
|
||||
*(int*) va_arg( *args, int* ) = in->readsofar;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'l': // we start with MODNORMAL and decrease the length first to MODLONG and after to MODLONGLONG
|
||||
case '%': // we are expecting the char '%' to be in the input stream, if not ERROR and return
|
||||
{
|
||||
if(mod==MODNORMAL)
|
||||
{
|
||||
mod=MODLONG;
|
||||
goto loopagain;
|
||||
}
|
||||
else if(mod==MODLONG)
|
||||
{
|
||||
mod=MODLONGLONG;
|
||||
goto loopagain;
|
||||
}
|
||||
else
|
||||
{
|
||||
mod=MODNORMAL;
|
||||
break; // we cannot have %lll
|
||||
}
|
||||
DBG( "'%' read");
|
||||
|
||||
if (__scanf_peek(in) != '%' ) return VALIDRETS;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'L': // idem, but only for Double and limiter only to MODLONG (no long long double available)
|
||||
case '*': // the next read, even if valid, will not be stored
|
||||
{
|
||||
mod=MODLONGDOUBLE;
|
||||
DBG( "'*' read");
|
||||
|
||||
SKIP = true;
|
||||
goto loopagain;
|
||||
}
|
||||
|
||||
case 'h':
|
||||
{
|
||||
if (MOD==MODNORMAL || MOD==MODSHORT)
|
||||
{
|
||||
MOD--;
|
||||
goto loopagain;
|
||||
}
|
||||
else return VALIDRETS; // we cannot have %hhh format modifier --> ERROR
|
||||
}
|
||||
|
||||
case 'l':
|
||||
{
|
||||
if (MOD==MODNORMAL || MOD==MODLONG)
|
||||
{
|
||||
MOD++;
|
||||
goto loopagain;
|
||||
}
|
||||
else return VALIDRETS; // we cannot have %ll format modifier --> ERROR
|
||||
}
|
||||
|
||||
case 'L':
|
||||
{
|
||||
if (MOD==MODNORMAL)
|
||||
{
|
||||
MOD=MODLONGDOUBLE;
|
||||
goto loopagain;
|
||||
}
|
||||
else return VALIDRETS; // we cannot have %LL format modifier --> ERROR
|
||||
}
|
||||
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
|
@ -218,119 +261,91 @@ int __scanf(
|
|||
case '8':
|
||||
case '9':
|
||||
{
|
||||
length = length * 10 + (int) ( format[i] - '0');
|
||||
in->readmaxlength = length;
|
||||
user_length = user_length * 10 + (int) ( format[pos] - '0' );
|
||||
in->readmaxlength = user_length;
|
||||
goto loopagain;
|
||||
}
|
||||
|
||||
case '%':
|
||||
{
|
||||
// NOthing to do this is just the character '%'
|
||||
in->readmaxlength = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'c':
|
||||
{
|
||||
// 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 );
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int u = 0; u < in->readmaxlength; u++ )
|
||||
{
|
||||
*c = __scanf_in( in );
|
||||
c++;
|
||||
}
|
||||
}
|
||||
in->readmaxlength=-1;
|
||||
ret++;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 'd':
|
||||
{
|
||||
// read a long int (in base 10 - decimal) from the current input stream
|
||||
// and store in the corresponding arg as a char by reference
|
||||
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 );
|
||||
mod = MODNORMAL;
|
||||
ret++;
|
||||
}
|
||||
break;
|
||||
ERROR = __strto_int( in, 10, NULL, &temp, false ); // base is 10 as for strtol
|
||||
if (ERROR != 0) return VALIDRETS;
|
||||
|
||||
if (SKIP) __scanf_store_i( temp, MODSKIP, args );
|
||||
else __scanf_store_i( temp, MOD, args );
|
||||
|
||||
VALIDRETS++;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 'i':
|
||||
{
|
||||
// read a long int (in base determined by the first character) from the current input stream
|
||||
// read a signed int (base to be defined at read) from the current input stream
|
||||
// and store in the corresponding arg as a char by reference
|
||||
|
||||
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 );
|
||||
mod = MODNORMAL;
|
||||
ret++;
|
||||
}
|
||||
break;
|
||||
ERROR = __strto_int( in, 0, NULL, &temp, false ); // base is 0 as for strtol
|
||||
if (ERROR != 0) return VALIDRETS;
|
||||
|
||||
if (SKIP) __scanf_store_i( temp, MODSKIP, args );
|
||||
else __scanf_store_i( temp, MOD, args );
|
||||
|
||||
VALIDRETS++;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 'u':
|
||||
{
|
||||
// read a unsigned long int (in base 10 - decimal) from the current input stream
|
||||
// read a unsigned int (in base 10 - decimal) from the current input stream
|
||||
// and store in the corresponding arg as a char by reference
|
||||
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 );
|
||||
mod = MODNORMAL;
|
||||
ret++;
|
||||
}
|
||||
break;
|
||||
ERROR = __strto_int( in, 10, NULL, &temp, false ); // base is 10 as for strtol - use_unsigned must be false (validated with glibc6.2 behaviour)
|
||||
if (ERROR != 0) return VALIDRETS;
|
||||
|
||||
if (SKIP) __scanf_store_i( temp, MODSKIP, args );
|
||||
else __scanf_store_i( temp, MOD, args );
|
||||
|
||||
VALIDRETS++;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 'o':
|
||||
{
|
||||
// read a unsigned long int (in base 8 - octal) from the current input stream
|
||||
// read a unsigned int (in base 8 - octal) from the current input stream
|
||||
// and store in the corresponding arg as a char by reference
|
||||
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 );
|
||||
mod = MODNORMAL;
|
||||
ret++;
|
||||
}
|
||||
break;
|
||||
ERROR = __strto_int( in, 8, NULL, &temp, true ); // base is 8 as for strtol
|
||||
if (ERROR != 0) return VALIDRETS;
|
||||
|
||||
if (SKIP) __scanf_store_i( temp, MODSKIP, args );
|
||||
else __scanf_store_i( temp, MOD, args );
|
||||
|
||||
VALIDRETS++;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 'x':
|
||||
case 'X':
|
||||
{
|
||||
// read a unsigned long int (in base 16 - hexadecimal) from the current input stream
|
||||
// read a unsigned int (in base 16 - hexadecimal) from the current input stream
|
||||
// and store in the corresponding arg as a char by reference
|
||||
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 );
|
||||
mod = MODNORMAL;
|
||||
ret++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
ERROR = __strto_int( in, 16, NULL, &temp, true ); // base is 16 as for strtol
|
||||
if (ERROR != 0) return VALIDRETS;
|
||||
|
||||
if (SKIP) __scanf_store_i( temp, MODSKIP, args );
|
||||
else __scanf_store_i( temp, MOD, args );
|
||||
|
||||
VALIDRETS++;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 'a':
|
||||
case 'A':
|
||||
|
@ -340,47 +355,485 @@ int __scanf(
|
|||
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 );
|
||||
if (err == 0)
|
||||
ERROR = __strto_fp( in, NULL, NULL, &temp );
|
||||
if (ERROR != 0) return VALIDRETS;
|
||||
|
||||
if (SKIP) __scanf_store_d( temp, MODSKIP, args );
|
||||
else __scanf_store_d( temp, MOD, args );
|
||||
|
||||
VALIDRETS++;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 'p':
|
||||
{
|
||||
long int dummy;
|
||||
|
||||
if (SKIP == false)
|
||||
{
|
||||
__scanf_store_d( temp, mod, args );
|
||||
mod = MODNORMAL;
|
||||
ret++;
|
||||
void *p = (void *) va_arg( *args, void** ); // get the adress of the target pointer (void**)
|
||||
ERROR = __strto_int( in, 0, p, NULL, true );
|
||||
}
|
||||
else ERROR = __strto_int( in, 0, &dummy, NULL, true );
|
||||
|
||||
if (ERROR == 0) VALIDRETS++;
|
||||
else return VALIDRETS;
|
||||
|
||||
SKIP = false;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
case 'c':
|
||||
{
|
||||
DBG( "'c' read");
|
||||
|
||||
char dummy;
|
||||
|
||||
if (SKIP == false)
|
||||
{
|
||||
char *c = (char *) va_arg( *args, char* );
|
||||
|
||||
if (in->readmaxlength==-1)
|
||||
{
|
||||
dummy = __scanf_peek( in );
|
||||
|
||||
if (dummy==EOF) return EOF;
|
||||
else
|
||||
{
|
||||
*c = __scanf_in( in );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( int u = 0; u < in->readmaxlength; u++ )
|
||||
{
|
||||
dummy = __scanf_peek( in );
|
||||
|
||||
if (dummy==EOF) return EOF;
|
||||
else
|
||||
{
|
||||
*c++ = __scanf_in( in );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (in->readmaxlength==-1)
|
||||
{
|
||||
dummy = __scanf_peek( in );
|
||||
|
||||
if (dummy==EOF) return EOF;
|
||||
else
|
||||
{
|
||||
__scanf_in( in );
|
||||
goto endcharskip;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( int u = 0; u < in->readmaxlength; u++ )
|
||||
{
|
||||
dummy = __scanf_peek( in );
|
||||
|
||||
if (dummy==EOF) return EOF;
|
||||
else __scanf_in( in );
|
||||
}
|
||||
goto endcharskip;
|
||||
}
|
||||
}
|
||||
|
||||
VALIDRETS++;
|
||||
|
||||
endcharskip:
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 's':
|
||||
{
|
||||
DBG( "'s' read");
|
||||
|
||||
__purge_space( in );
|
||||
|
||||
char dummy;
|
||||
int curstrlength = 0;
|
||||
|
||||
if (SKIP == false)
|
||||
{
|
||||
char *c = (char *) va_arg( *args, char* );
|
||||
|
||||
if (in->readmaxlength==-1)
|
||||
{
|
||||
loopstring:
|
||||
|
||||
dummy = __scanf_peek( in );
|
||||
|
||||
if (dummy==EOF && curstrlength==0) return VALIDRETS;
|
||||
|
||||
if (isspace(dummy) || ( (dummy==EOF && curstrlength!=0) ))
|
||||
{
|
||||
*c = 0;
|
||||
goto loopstringend;
|
||||
}
|
||||
else
|
||||
{
|
||||
*c++ = __scanf_in( in );
|
||||
curstrlength++;
|
||||
goto loopstring;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( int u = 0; u < in->readmaxlength; u++ )
|
||||
{
|
||||
dummy = __scanf_peek( in );
|
||||
|
||||
if (dummy==EOF && curstrlength==0) return VALIDRETS;
|
||||
|
||||
if (isspace(dummy) || ( (dummy==EOF && curstrlength!=0) ))
|
||||
{
|
||||
*c = 0;
|
||||
goto loopstringend;
|
||||
}
|
||||
else
|
||||
{
|
||||
*c++ = __scanf_in( in );
|
||||
curstrlength++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (in->readmaxlength==-1)
|
||||
{
|
||||
loopstringskip:
|
||||
|
||||
dummy = __scanf_peek( in );
|
||||
|
||||
if (dummy==EOF && curstrlength==0) return VALIDRETS;
|
||||
|
||||
if (isspace(dummy) || ( (dummy==EOF && curstrlength!=0) ))
|
||||
{
|
||||
goto loopstringendskip;
|
||||
}
|
||||
else
|
||||
{
|
||||
__scanf_in( in );
|
||||
curstrlength++;
|
||||
goto loopstringskip;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( int u = 0; u < in->readmaxlength; u++ )
|
||||
{
|
||||
dummy = __scanf_peek( in );
|
||||
|
||||
if (dummy==EOF && curstrlength==0) return VALIDRETS;
|
||||
|
||||
if (isspace(dummy) || ( (dummy==EOF && curstrlength!=0) ))
|
||||
{
|
||||
goto loopstringendskip;
|
||||
}
|
||||
else
|
||||
{
|
||||
__scanf_in( in );
|
||||
curstrlength++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
loopstringend:
|
||||
|
||||
VALIDRETS++;
|
||||
|
||||
loopstringendskip:
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else // we are looking for a specific character in the input stream
|
||||
{
|
||||
if( format[pos] == __scanf_peek( in )) // if the next char of the stream is corresponding, we validate the read and go to the following char
|
||||
{
|
||||
__scanf_in( in );
|
||||
pos++; // TODO : check if VALIDRETS needs to be incremented
|
||||
}
|
||||
return VALIDRETS; // else we return the number of valid read
|
||||
}
|
||||
|
||||
pos++;
|
||||
|
||||
}
|
||||
|
||||
__scanf_end( in );
|
||||
|
||||
return VALIDRETS;
|
||||
|
||||
/*
|
||||
int i=0;
|
||||
int ret = 0;
|
||||
int err = 0;
|
||||
|
||||
int mod = MODNORMAL;
|
||||
int length = 0;
|
||||
|
||||
in->readsofar = 0;
|
||||
in->readmaxlength = -1;
|
||||
in->purgewhitespace = false;
|
||||
in->skip = false;
|
||||
|
||||
__scanf_start( in );
|
||||
|
||||
|
||||
while( format[i]!= '\0' )
|
||||
{
|
||||
in->readmaxlength = -1;
|
||||
mod = MODNORMAL;
|
||||
length = 0;
|
||||
|
||||
if ( format[i] == '%' ) {// read conversion
|
||||
loopagain:
|
||||
|
||||
i++;
|
||||
|
||||
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 || mod==MODSHORT) {
|
||||
mod--;
|
||||
goto loopagain;
|
||||
}
|
||||
return ret; // we cannot have %hhh
|
||||
}
|
||||
|
||||
case 'l': { // we start with MODNORMAL and decrease the length first to MODLONG and after to MODLONGLONG
|
||||
if(mod==MODNORMAL || mod==MODLONG) {
|
||||
mod++;
|
||||
goto loopagain;
|
||||
}
|
||||
return ret; // we cannot have %lll
|
||||
}
|
||||
|
||||
case 'L': // idem, but only for Double and limiter only to MODLONG (no long long double available)
|
||||
{
|
||||
if (mod==MODNORMAL) {
|
||||
mod=MODLONGDOUBLE;
|
||||
goto loopagain;
|
||||
}
|
||||
return ret; // we cannot have %LL
|
||||
}
|
||||
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': {
|
||||
length = length * 10 + (int) ( format[i] - '0' );
|
||||
in->readmaxlength = length;
|
||||
goto loopagain;
|
||||
}
|
||||
|
||||
case '%': {
|
||||
char c = __scanf_peek( in );
|
||||
if (c=='%') __scanf_in( in );
|
||||
else return ret;
|
||||
|
||||
// Nothing to do this is just the character '%'
|
||||
in->readmaxlength = -1;
|
||||
in->purgewhitespace = false;
|
||||
in->skip = false;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'c': {
|
||||
// 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) {
|
||||
if (in->skip==false) *c = __scanf_in( in );
|
||||
else __scanf_in( in );
|
||||
}
|
||||
else {
|
||||
for(int u = 0; u < in->readmaxlength; u++ ) {
|
||||
if (in->skip==false) {
|
||||
*c = __scanf_in( in );
|
||||
c++;
|
||||
}
|
||||
else __scanf_in( in );
|
||||
}
|
||||
}
|
||||
|
||||
in->readmaxlength=-1;
|
||||
in->skip = false;
|
||||
ret++;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 'd': {
|
||||
// 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) {
|
||||
if (in->skip==false) __scanf_store_i( temp, mod, args );
|
||||
else __scanf_store_i( temp, MODSKIP, args );
|
||||
in->skip = false;
|
||||
mod = MODNORMAL;
|
||||
ret++;
|
||||
}
|
||||
else return ret;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'i': {
|
||||
// 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) {
|
||||
if (in->skip==false) __scanf_store_i( temp, mod, args );
|
||||
else __scanf_store_i( temp, MODSKIP, args );
|
||||
in->skip = false;
|
||||
mod = MODNORMAL;
|
||||
ret++;
|
||||
}
|
||||
else return ret;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
case 'u': {
|
||||
// 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) {
|
||||
if (in->skip==false) __scanf_store_i( temp, mod, args );
|
||||
else __scanf_store_i( temp, MODSKIP, args );
|
||||
in->skip = false;
|
||||
mod = MODNORMAL;
|
||||
ret++;
|
||||
}
|
||||
else return ret;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'o': {
|
||||
// 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) {
|
||||
if (in->skip==false) __scanf_store_i( temp, mod, args );
|
||||
else __scanf_store_i( temp, MODSKIP, args );
|
||||
in->skip = false;
|
||||
mod = MODNORMAL;
|
||||
ret++;
|
||||
}
|
||||
else return ret;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'x':
|
||||
case 'X': {
|
||||
// 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) {
|
||||
if (in->skip==false) __scanf_store_i( temp, mod, args );
|
||||
else __scanf_store_i( temp, MODSKIP, args );
|
||||
in->skip = false;
|
||||
mod = MODNORMAL;
|
||||
ret++;
|
||||
}
|
||||
else return ret;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'a':
|
||||
case 'A':
|
||||
case 'e':
|
||||
case 'E':
|
||||
case 'f':
|
||||
case 'F':
|
||||
case 'g':
|
||||
case 'G': {
|
||||
in->purgewhitespace = false;
|
||||
long double temp;
|
||||
err = __strto_fp( in, NULL, NULL, &temp );
|
||||
if (err == 0) {
|
||||
if (in->skip==false) __scanf_store_d( temp, mod, args );
|
||||
else __scanf_store_d( temp, MODSKIP, args );
|
||||
in->skip = false;
|
||||
mod = MODNORMAL;
|
||||
ret++;
|
||||
}
|
||||
else return ret;
|
||||
break;
|
||||
}
|
||||
|
||||
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* );
|
||||
char temp;
|
||||
if (in->readmaxlength==-1) // read the maximum number of non-whitespace characters
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
if (in->readmaxlength==-1) { // read the maximum number of non-whitespace characters
|
||||
for(;;) {
|
||||
temp = __scanf_peek( in );
|
||||
if (!isspace(temp) && temp != EOF)
|
||||
{
|
||||
*c = __scanf_in( in );
|
||||
c++;
|
||||
if (!isspace(temp) && temp != EOF) {
|
||||
if (in->skip == false ) {
|
||||
*c = __scanf_in( in );
|
||||
c++;
|
||||
}
|
||||
else __scanf_in( in );
|
||||
}
|
||||
else break;
|
||||
}
|
||||
*c = '\0'; // add the mandatory terminal '\0'
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int u = 0; u < in->readmaxlength; u++ )
|
||||
{
|
||||
else {
|
||||
for(int u = 0; u < in->readmaxlength; u++ ) {
|
||||
temp = __scanf_peek( in );
|
||||
if (!isspace(temp) && temp != EOF)
|
||||
{
|
||||
*c = __scanf_in( in );
|
||||
c++;
|
||||
if (!isspace(temp) && temp != EOF) {
|
||||
if (in->skip == false ) {
|
||||
*c = __scanf_in( in );
|
||||
c++;
|
||||
}
|
||||
else __scanf_in( in );
|
||||
}
|
||||
else break;
|
||||
}
|
||||
|
@ -391,32 +844,45 @@ int __scanf(
|
|||
break;
|
||||
}
|
||||
|
||||
case 'n':
|
||||
{
|
||||
// rreturn the number of characters read so far
|
||||
case 'n': {
|
||||
in->purgewhitespace = false;
|
||||
// return the number of characters read so far
|
||||
int *n = (int *) va_arg( *args, int* );
|
||||
*n = in->readsofar;
|
||||
// TODO: need to chack if the '%n' with a valid results counts for the return of scanf()
|
||||
ret++;
|
||||
break;
|
||||
}
|
||||
|
||||
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 );
|
||||
case 'p': {
|
||||
in->purgewhitespace = false;
|
||||
long int dummy;
|
||||
|
||||
if (in->skip == false) {
|
||||
void *p = (void *) va_arg( *args, void** ); // get the adress of the target pointer (void**)
|
||||
err = __strto_int( in, 0, p, NULL, true );
|
||||
}
|
||||
else err = __strto_int( in, 0, &dummy, NULL, true );
|
||||
|
||||
if (err == 0) ret++;
|
||||
else return 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
|
||||
if (err!=0) break; // an ERROR occured somewhere whiloe parsing the values
|
||||
}
|
||||
|
||||
__scanf_end( in );
|
||||
|
||||
return ret;
|
||||
*/
|
||||
|
||||
}
|
Loading…
Reference in New Issue