mirror of
https://git.planet-casio.com/Vhex-Kernel-Core/fxlibc.git
synced 2024-12-28 04:23:38 +01:00
stdio: simplify output size management in scanf
This commit is contained in:
parent
69eadb67d2
commit
55ae7df318
2 changed files with 65 additions and 122 deletions
|
@ -37,21 +37,6 @@ void __scanf_end(struct __scanf_input *in)
|
||||||
in->str--;
|
in->str--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
MODSKIP,
|
|
||||||
MODCHAR,
|
|
||||||
MODSHORT,
|
|
||||||
MODNORMAL,
|
|
||||||
MODLONG,
|
|
||||||
MODLONGLONG,
|
|
||||||
MODLONGDOUBLE,
|
|
||||||
MODINTMAXT,
|
|
||||||
MODSIZET,
|
|
||||||
MODPTRDIFFT,
|
|
||||||
};
|
|
||||||
|
|
||||||
void __purge_space( struct __scanf_input * __restrict__ in )
|
void __purge_space( struct __scanf_input * __restrict__ in )
|
||||||
{
|
{
|
||||||
while (isspace(__scanf_peek(in))) __scanf_in(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)
|
void __scanf_store_i(int64_t value, int size, va_list *args)
|
||||||
{
|
{
|
||||||
if(size == MODSKIP) return;
|
if(size == 1)
|
||||||
|
|
||||||
if(size == MODCHAR)
|
|
||||||
*va_arg(*args, int8_t *) = value;
|
*va_arg(*args, int8_t *) = value;
|
||||||
else if(size == MODSHORT)
|
else if(size == 2)
|
||||||
*va_arg(*args, int16_t *) = value;
|
*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;
|
*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)
|
void __scanf_store_d(long double value, int size, va_list *args)
|
||||||
{
|
{
|
||||||
if (size==MODSKIP) return;
|
if(size == sizeof(float))
|
||||||
|
|
||||||
if(size == MODLONG)
|
|
||||||
*va_arg(*args, double *) = value;
|
|
||||||
else if(size == MODLONGDOUBLE)
|
|
||||||
*va_arg(*args, long double *) = value;
|
|
||||||
else
|
|
||||||
*va_arg(*args, float *) = value;
|
*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 */
|
/* STATUS OF __scanf DEVELOPMENT */
|
||||||
|
@ -239,11 +214,9 @@ int __scanf(
|
||||||
{
|
{
|
||||||
|
|
||||||
bool skip = false;
|
bool skip = false;
|
||||||
|
int MOD = sizeof(int);
|
||||||
int MOD = MODNORMAL;
|
|
||||||
|
|
||||||
in->readsofar = 0; // we haven't started to read char from the input stream
|
in->bytes_read = 0; // we haven't started to read char from the input stream
|
||||||
in->readmaxlength = -1; // no specific maximum length to read is defined yet
|
|
||||||
|
|
||||||
int validrets = 0; // to be incremented each time we successfully read and store an input as per the format
|
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 err = 0; // err control on __strto_xx( ) functions
|
||||||
|
@ -255,9 +228,8 @@ int __scanf(
|
||||||
// TODO: No __scanf_end() in any of the "return validrets"!!
|
// TODO: No __scanf_end() in any of the "return validrets"!!
|
||||||
|
|
||||||
while( format[pos] != 0 ) {
|
while( format[pos] != 0 ) {
|
||||||
in->readmaxlength = -1;
|
|
||||||
user_length = 0;
|
user_length = 0;
|
||||||
MOD = MODNORMAL;
|
MOD = sizeof(int);
|
||||||
skip = false;
|
skip = false;
|
||||||
|
|
||||||
__allow_all_set();
|
__allow_all_set();
|
||||||
|
@ -268,7 +240,9 @@ int __scanf(
|
||||||
// we will have to manage a given format
|
// we will have to manage a given format
|
||||||
else if( format[pos] == '%' ) {
|
else if( format[pos] == '%' ) {
|
||||||
|
|
||||||
in->readmaxlength = INT_MAX;
|
int readmaxlength = INT_MAX;
|
||||||
|
char size_letter = 0;
|
||||||
|
|
||||||
// main loop
|
// main loop
|
||||||
loopagain:
|
loopagain:
|
||||||
|
|
||||||
|
@ -282,7 +256,7 @@ int __scanf(
|
||||||
int currentlength = 0;
|
int currentlength = 0;
|
||||||
// we need to assign the read char to the corresponding pointer
|
// we need to assign the read char to the corresponding pointer
|
||||||
char *c = skip ? NULL : va_arg(*args, char *);
|
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_peek(in);
|
int temp = __scanf_peek(in);
|
||||||
if(__is_allowed(temp)) {
|
if(__is_allowed(temp)) {
|
||||||
__scanf_in(in);
|
__scanf_in(in);
|
||||||
|
@ -301,10 +275,9 @@ int __scanf(
|
||||||
}
|
}
|
||||||
|
|
||||||
// return the number of char read so far (cannot be skipped %*n is not valid)
|
// return the number of char read so far (cannot be skipped %*n is not valid)
|
||||||
case 'n': {
|
case 'n':
|
||||||
*(int*) va_arg( *args, int* ) = in->readsofar;
|
*va_arg(*args, int *) = in->bytes_read;
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
// we are expecting the char '%' to be in the input stream, if not err and return
|
// we are expecting the char '%' to be in the input stream, if not err and return
|
||||||
case '%': {
|
case '%': {
|
||||||
|
@ -314,69 +287,36 @@ int __scanf(
|
||||||
}
|
}
|
||||||
|
|
||||||
// the next read, even if valid, will not be stored
|
// the next read, even if valid, will not be stored
|
||||||
case '*': {
|
case '*':
|
||||||
skip = true;
|
skip = true;
|
||||||
goto loopagain;
|
goto loopagain;
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'h': {
|
case 'h':
|
||||||
if (MOD==MODNORMAL || MOD==MODSHORT) {
|
MOD = (size_letter == 'h') ? sizeof(char) : sizeof(short);
|
||||||
MOD--;
|
size_letter = 'h';
|
||||||
goto loopagain;
|
goto loopagain;
|
||||||
}
|
case 'l':
|
||||||
else return validrets; // we cannot have %hhh format modifier --> err
|
MOD = (size_letter == 'l') ? sizeof(long long) : sizeof(long);
|
||||||
break;
|
/* FP conversions will adjust to sizeof(double) later */
|
||||||
}
|
size_letter = 'l';
|
||||||
|
goto loopagain;
|
||||||
case 'l': {
|
case 'L':
|
||||||
if (MOD==MODNORMAL || MOD==MODLONG) {
|
MOD = sizeof(long double);
|
||||||
MOD++;
|
size_letter = 'L';
|
||||||
goto loopagain;
|
goto loopagain;
|
||||||
}
|
case 'j':
|
||||||
else return validrets; // we cannot have %ll format modifier --> err
|
MOD = sizeof(intmax_t);
|
||||||
break;
|
goto loopagain;
|
||||||
}
|
case 'z':
|
||||||
|
MOD = sizeof(size_t);
|
||||||
case 'L': {
|
goto loopagain;
|
||||||
if (MOD==MODNORMAL) {
|
case 't':
|
||||||
MOD=MODLONGDOUBLE;
|
MOD = sizeof(ptrdiff_t);
|
||||||
goto loopagain;
|
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 '0' ... '9': {
|
case '0' ... '9': {
|
||||||
user_length = user_length * 10 + (int) ( format[pos] - '0' );
|
user_length = user_length * 10 + (int) ( format[pos] - '0' );
|
||||||
in->readmaxlength = user_length;
|
readmaxlength = user_length;
|
||||||
goto loopagain;
|
goto loopagain;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -395,10 +335,10 @@ int __scanf(
|
||||||
|
|
||||||
long long int temp;
|
long long int temp;
|
||||||
err = __strto_int(in, base, NULL, &temp, use_unsigned,
|
err = __strto_int(in, base, NULL, &temp, use_unsigned,
|
||||||
in->readmaxlength);
|
readmaxlength);
|
||||||
if (err == EOF && validrets == 0) return EOF;
|
if (err == EOF && validrets == 0) return EOF;
|
||||||
if (err != 0) return validrets;
|
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 );
|
else __scanf_store_i( temp, MOD, args );
|
||||||
validrets++;
|
validrets++;
|
||||||
break;
|
break;
|
||||||
|
@ -411,15 +351,21 @@ int __scanf(
|
||||||
case 'f':
|
case 'f':
|
||||||
case 'F':
|
case 'F':
|
||||||
case 'g':
|
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
|
// read a double from the current input stream
|
||||||
// and store in the corresponding arg as a char by reference
|
// and store in the corresponding arg as a char by reference
|
||||||
long double temp;
|
long double temp;
|
||||||
err = __strto_fp( in, NULL, NULL, &temp,
|
err = __strto_fp( in, NULL, NULL, &temp,
|
||||||
in->readmaxlength);
|
readmaxlength);
|
||||||
if (err == EOF && validrets == 0) return EOF;
|
if (err == EOF && validrets == 0) return EOF;
|
||||||
if (err != 0) return validrets;
|
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 );
|
else __scanf_store_d( temp, MOD, args );
|
||||||
validrets++;
|
validrets++;
|
||||||
break;
|
break;
|
||||||
|
@ -430,10 +376,10 @@ int __scanf(
|
||||||
if (!skip) {
|
if (!skip) {
|
||||||
void *p = (void *) va_arg( *args, void** ); // get the adress of the target pointer (void**)
|
void *p = (void *) va_arg( *args, void** ); // get the adress of the target pointer (void**)
|
||||||
err = __strto_int( in, 0, p, NULL, true,
|
err = __strto_int( in, 0, p, NULL, true,
|
||||||
in->readmaxlength);
|
readmaxlength);
|
||||||
}
|
}
|
||||||
else err = __strto_int( in, 0, &temp, NULL, true,
|
else err = __strto_int( in, 0, &temp, NULL, true,
|
||||||
in->readmaxlength);
|
readmaxlength);
|
||||||
if (err == 0) validrets++;
|
if (err == 0) validrets++;
|
||||||
else return validrets;
|
else return validrets;
|
||||||
skip = false;
|
skip = false;
|
||||||
|
@ -441,11 +387,11 @@ int __scanf(
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'c': {
|
case 'c': {
|
||||||
if(in->readmaxlength == INT_MAX)
|
if(readmaxlength == INT_MAX)
|
||||||
in->readmaxlength = 1;
|
readmaxlength = 1;
|
||||||
char *c = skip ? NULL : va_arg(*args, char *);
|
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);
|
int temp = __scanf_in(in);
|
||||||
if(temp==EOF) return EOF;
|
if(temp==EOF) return EOF;
|
||||||
else if(c) *c++ = temp;
|
else if(c) *c++ = temp;
|
||||||
|
@ -460,7 +406,7 @@ int __scanf(
|
||||||
__purge_space(in);
|
__purge_space(in);
|
||||||
|
|
||||||
char *c = skip ? NULL : va_arg(*args, char *);
|
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);
|
temp = __scanf_peek(in);
|
||||||
if(temp==EOF && curstrlength==0) return validrets;
|
if(temp==EOF && curstrlength==0) return validrets;
|
||||||
if(isspace(temp) || ((temp==EOF && curstrlength!=0))) {
|
if(isspace(temp) || ((temp==EOF && curstrlength!=0))) {
|
||||||
|
|
|
@ -18,15 +18,12 @@ struct __scanf_input {
|
||||||
char const * __restrict__ str;
|
char const * __restrict__ str;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
|
||||||
// max char to read from the input stream as per user length modifier
|
/* Single-character lookahead buffer */
|
||||||
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;
|
|
||||||
|
|
||||||
int buffer;
|
int buffer;
|
||||||
};
|
|
||||||
|
|
||||||
|
/* Total numbers of bytes read in a scall to *scanf() */
|
||||||
|
int bytes_read;
|
||||||
|
};
|
||||||
|
|
||||||
/* Generic formatted scaning. */
|
/* Generic formatted scaning. */
|
||||||
extern int __scanf(
|
extern int __scanf(
|
||||||
|
@ -46,7 +43,7 @@ static inline int __scanf_in(struct __scanf_input *__in)
|
||||||
{
|
{
|
||||||
int c = __in->buffer;
|
int c = __in->buffer;
|
||||||
__in->buffer = __scanf_fetch(__in);
|
__in->buffer = __scanf_fetch(__in);
|
||||||
__in->readsofar++;
|
__in->bytes_read++;
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue