stdlib: scanf implementation by SlyVTT

Authored-By: Slyvtt <pillot.sylvain@gmail.com>
This commit is contained in:
Slyvtt 2023-02-17 20:24:01 +01:00 committed by Lephenixnoir
parent 031e0ccb65
commit 09b33ca2fa
No known key found for this signature in database
GPG key ID: 1BBA026E13FC0495
19 changed files with 795 additions and 31 deletions

View file

@ -124,6 +124,7 @@ set(SOURCES
src/stdio/fputs.c src/stdio/fputs.c
src/stdio/fread.c src/stdio/fread.c
src/stdio/freopen.c src/stdio/freopen.c
src/stdio/fscanf.c
src/stdio/fseek.c src/stdio/fseek.c
src/stdio/fsetpos.c src/stdio/fsetpos.c
src/stdio/ftell.c src/stdio/ftell.c
@ -145,19 +146,24 @@ set(SOURCES
src/stdio/puts.c src/stdio/puts.c
src/stdio/remove.c src/stdio/remove.c
src/stdio/rewind.c src/stdio/rewind.c
src/stdio/scanf.c
src/stdio/scanf/scan.c src/stdio/scanf/scan.c
src/stdio/setbuf.c src/stdio/setbuf.c
src/stdio/setvbuf.c src/stdio/setvbuf.c
src/stdio/snprintf.c src/stdio/snprintf.c
src/stdio/sprintf.c src/stdio/sprintf.c
src/stdio/sscanf.c
src/stdio/streams.c src/stdio/streams.c
src/stdio/ungetc.c src/stdio/ungetc.c
src/stdio/vasprintf.c src/stdio/vasprintf.c
src/stdio/vdprintf.c src/stdio/vdprintf.c
src/stdio/vfprintf.c src/stdio/vfprintf.c
src/stdio/vfscanf.c
src/stdio/vprintf.c src/stdio/vprintf.c
src/stdio/vscanf.c
src/stdio/vsnprintf.c src/stdio/vsnprintf.c
src/stdio/vsprintf.c src/stdio/vsprintf.c
src/stdio/vsscanf.c
# stdlib # stdlib
src/stdlib/abort.c src/stdlib/abort.c
src/stdlib/abs.c src/stdlib/abs.c

View file

@ -1,7 +1,14 @@
#ifndef __STDIO_P_H__ #ifndef __SCANF_H__
# define __STDIO_P_H__ # define __SCANF_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h> #include <stdio.h>
#include <stdbool.h>
/* /*
** General utilities for scanf(); we expose them here as we use subfunctions of ** General utilities for scanf(); we expose them here as we use subfunctions of
@ -16,9 +23,25 @@
struct __scanf_input { 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
int readmaxlength;
int currentlength;
// 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;
}; };
/* Generic formatted scaning. */
extern int __scanf(
struct __scanf_input * __restrict__ __in,
char const * __restrict__ __format,
va_list *__args);
/* Initialize the input by feeding the buffer byte. */ /* Initialize the input by feeding the buffer byte. */
void __scanf_start(struct __scanf_input *__in); void __scanf_start(struct __scanf_input *__in);
@ -30,16 +53,27 @@ 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->currentlength++;
return c; return c;
} }
/* Peek the next byte without advancing. */ /* Peek the next byte without advancing. */
static inline int __scanf_peek(struct __scanf_input *__in) static inline int __scanf_peek(struct __scanf_input *__in)
{ {
return __in->buffer; if (__in->readmaxlength==-1 || __in->currentlength<__in->readmaxlength )
return __in->buffer;
else return 0;
} }
/* Close the input by unsending the buffer once finished. */ /* Close the input by unsending the buffer once finished. */
void __scanf_end(struct __scanf_input *__in); void __scanf_end(struct __scanf_input *__in);
#endif /* __STDIO_P_H__ */
#ifdef __cplusplus
}
#endif
#endif /* __SCANF_H__ */

View file

@ -3,7 +3,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdbool.h> #include <stdbool.h>
#include "../stdio/stdio_p.h" #include <fxlibc/scanf.h>
/* /*
** Parse an integer from a string. This is the base function for strtol, ** Parse an integer from a string. This is the base function for strtol,

17
src/stdio/fscanf.c Normal file
View file

@ -0,0 +1,17 @@
#include <stdio.h>
#include <fxlibc/scanf.h>
int fscanf(FILE * restrict fp, char const * restrict fmt, ...)
{
struct __scanf_input in = {
.fp = fp,
};
va_list args;
va_start(args, fmt);
int count = __scanf(&in, fmt, &args);
va_end(args);
return count;
}

17
src/stdio/scanf.c Normal file
View file

@ -0,0 +1,17 @@
#include <stdio.h>
#include <fxlibc/scanf.h>
int scanf(char const * restrict fmt, ...)
{
struct __scanf_input in = {
.fp = stdin,
};
va_list args;
va_start(args, fmt);
int count = __scanf(&in, fmt, &args);
va_end(args);
return count;
}

View file

@ -1,37 +1,669 @@
#include <stdio.h> #include <stdio.h>
#include "../stdio_p.h" #include <ctype.h>
#include "../../stdlib/stdlib_p.h" #include <fxlibc/scanf.h>
#include <fxlibc/stdlib_p.h>
#include <stdbool.h>
void __scanf_start(struct __scanf_input *__in) void __scanf_start(struct __scanf_input *in)
{ {
if(__in->fp) if(in->fp)
__in->buffer = fgetc(__in->fp); in->buffer = fgetc(in->fp);
else { else {
__in->buffer = *__in->str; in->buffer = (*in->str ? *in->str : EOF);
__in->str += (__in->buffer != 0); in->str += (in->buffer != 0);
} }
} }
int __scanf_fetch(struct __scanf_input *__in) int __scanf_fetch(struct __scanf_input *in)
{ {
if(__in->fp) if(in->fp)
return fgetc(__in->fp); return fgetc(in->fp);
int c = *__in->str; int c = *in->str;
if(c == 0) if(c == 0)
return EOF; return EOF;
__in->str++; in->str++;
return c; return c;
} }
void __scanf_end(struct __scanf_input *__in) void __scanf_end(struct __scanf_input *in)
{ {
if(__in->buffer == EOF) if(in->buffer == EOF)
return; return;
if(__in->fp) if(in->fp)
ungetc(__in->buffer, __in->fp); ungetc(in->buffer, in->fp);
else else
__in->str--; 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);
}
void __scanf_store_i(int64_t value, int size, va_list *args)
{
if(size == MODSKIP) return;
if(size == MODCHAR)
*va_arg(*args, int8_t *) = value;
else if(size == MODSHORT)
*va_arg(*args, int16_t *) = value;
else if(size == MODLONGLONG)
*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
*va_arg(*args, float *) = value;
}
/* STATUS OF __scanf DEVELOPMENT */
// XX = not done yet (but will be done)
// OK = OK, done and tested
// -- = not applicable
// NO = not supported (and will not be done) only for %lc as long char are not supported by gint
/*************************************************************************************************************/
/* Specifier * Explanation * num * hh * h *none* l * ll * j * z * t * L */
/*************************************************************************************************************/
/* % * Parse literal '%' * -- * -- * -- * OK * -- * -- * -- * -- * -- * -- */
/*************************************************************************************************************/
/* c * match a char or several char * OK * -- * -- * OK * NO * -- * -- * -- * -- * -- */
/*************************************************************************************************************/
/* s * match a string * OK * -- * -- * OK * NO * -- * -- * -- * -- * -- */
/*************************************************************************************************************/
/* [set] * match a set of char * OK * -- * -- * OK * -- * -- * -- * -- * -- * -- */
/*************************************************************************************************************/
/* d * match a decimal integer * OK * OK * OK * OK * OK * OK * OK * OK * OK * -- */
/*************************************************************************************************************/
/* i * match an integer * OK * OK * OK * OK * OK * OK * OK * OK * OK * -- */
/*************************************************************************************************************/
/* d * match an unsigned decimal integer * OK * OK * OK * OK * OK * OK * OK * OK * OK * -- */
/*************************************************************************************************************/
/* o * match a unsigned octal integer * OK * OK * OK * OK * OK * OK * OK * OK * OK * -- */
/*************************************************************************************************************/
/* x,X * match a unsigned hexadecimal integer * OK * OK * OK * OK * OK * OK * OK * OK * OK * -- */
/*************************************************************************************************************/
/* n * return the nb of chars read so far * -- * -- * -- * OK * -- * -- * -- * -- * -- * -- */
/*************************************************************************************************************/
/* a,A * match a floating point number * OK * -- * -- * OK * OK * -- * -- * -- * -- * OK */
/* e,E * match a floating point number * OK * -- * -- * OK * OK * -- * -- * -- * -- * OK */
/* f,F * match a floating point number * OK * -- * -- * OK * OK * -- * -- * -- * -- * OK */
/* g,G * match a floating point number * OK * -- * -- * OK * OK * -- * -- * -- * -- * OK */
/*************************************************************************************************************/
/* p * match a pointer * -- * -- * -- * OK * -- * -- * -- * -- * -- * -- */
/*************************************************************************************************************/
// %ms and %m[set] are not implemented (with memory allocation while parsing a chain or a set of characters)
/* list of allowed char given by a set %[], this is updated at every set */
bool __asciiallowed[256] = { true };
/* unallow all the char for the current set */
void __unallow_all_set( void )
{
for(int u =0; u<=255; u++)
__asciiallowed[u]=false;
}
/* allow all the char for the current set */
void __allow_all_set( void )
{
for(int u =0; u<=255; u++)
__asciiallowed[u]=true;
}
/* allo a range of char for the current set */
/* note1 : c1 and c2 do not to be sorted */
/* note2 : not sur if C standard requires to be ordered or not */
void __define_set_range( char c1, char c2, bool value )
{
char beg = (c1 < c2 ? c1 : c2 );
char end = (c1 >= c2 ? c1 : c2 );
for (int u=beg; u<=end; u++)
__asciiallowed[u] = value;
}
/* return true if the char is in the allowed set or false otherwise */
bool __is_allowed( const unsigned char c )
{
return __asciiallowed[ c ];
}
/* return 0 if Ok or -1 if syntax err in the set format */
int __scanset(char const * __restrict__ format, int *pos )
{
int __sor = 0;
int __eor = 0;
bool __neg = false;
__unallow_all_set();
(*pos)++;
// next will be a "negation" set
if (format[*pos] == '^' ) {
__neg = true;
(*pos)++;
__allow_all_set();
// the char ']' is part of the set
if (format[*pos] == ']' ) {
__asciiallowed[ ']' ] = !__neg;
(*pos)++;
}
}
// the char ']' is included in the allowed set
else if (format[*pos] == ']' ) {
__neg = false;
// the char ']' is part of the set
if (format[*pos] == ']' ) {
__asciiallowed[ ']' ] = !__neg;
(*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;
}
// the char '-' indicates a range of char to be included into the set
else {
(*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;
}
}
int __scanf(
struct __scanf_input * __restrict__ in,
char const * __restrict__ format,
va_list *args)
{
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
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 user_length = 0; // length defined by user with a %xx modifier
int pos = 0; // current pos in the format string
__scanf_start( in );
while( format[pos] != 0 ) {
in->readmaxlength = -1;
user_length = 0;
MOD = MODNORMAL;
skip = false;
__allow_all_set();
if( format[pos] == ' ' ) {
__purge_space(in);
}
// we will have to manage a given format
else if( format[pos] == '%' ) {
in->readmaxlength = -1;
// main loop
loopagain:
pos++;
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==-1) {
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(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;
}
}
else
{
if (in->readmaxlength==-1) {
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(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:
break;
}
// return the number of char read so far (cannot be skipped %*n is not valid)
case 'n': {
*(int*) va_arg( *args, int* ) = in->readsofar;
break;
}
// we are expecting the char '%' to be in the input stream, if not err and return
case '%': {
if (__scanf_peek(in) != '%') return validrets;
else __scanf_in( in );
break;
}
// the next read, even if valid, will not be stored
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 '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9': {
user_length = user_length * 10 + (int) ( format[pos] - '0' );
in->readmaxlength = user_length;
goto loopagain;
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) return validrets;
if (skip) __scanf_store_i( temp, MODSKIP, args );
else __scanf_store_i( temp, MOD, args );
validrets++;
break;
}
case 'i': {
// 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) return validrets;
if (skip) __scanf_store_i( temp, MODSKIP, args );
else __scanf_store_i( temp, MOD, args );
validrets++;
break;
}
case 'u': {
// 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, false ); // base is 10 as for strtol - use_unsigned must be false (validated with glibc6.2 behaviour)
if (err != 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 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) 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 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) return validrets;
if (skip) __scanf_store_i( temp, MODSKIP, args );
else __scanf_store_i( temp, MOD, args );
validrets++;
break;
}
case 'a':
case 'A':
case 'e':
case 'E':
case 'f':
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) return validrets;
if (skip) __scanf_store_d( temp, MODSKIP, args );
else __scanf_store_d( temp, MOD, args );
validrets++;
break;
}
case 'p': {
long int temp;
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 );
}
else err = __strto_int( in, 0, &temp, NULL, true );
if (err == 0) validrets++;
else return validrets;
skip = false;
break;
}
case 'c': {
char temp;
if (!skip) {
char *c = (char *) va_arg( *args, char* );
if (in->readmaxlength==-1) {
temp = __scanf_peek( in );
if (temp==EOF) return EOF;
else *c = __scanf_in( in );
}
else {
for( 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==-1) {
temp = __scanf_peek( in );
if (temp==EOF) return EOF;
else {
__scanf_in( in );
goto endcharskip;
}
}
else {
for( int u = 0; u < in->readmaxlength; u++ ) {
temp = __scanf_peek( in );
if (temp==EOF) return EOF;
else __scanf_in( in );
}
goto endcharskip;
}
}
validrets++;
endcharskip:
break;
}
case 's': {
char temp;
int curstrlength = 0;
__purge_space( in );
if (!skip) {
char *c = (char *) va_arg( *args, char* );
if (in->readmaxlength==-1) {
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;
}
}
else {
for( 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++;
}
}
}
}
else {
if (in->readmaxlength==-1) {
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( 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;
}
}
}
// we are looking for a specific character in the input stream
else {
// if the next char of the stream is corresponding, we validate the read and go to the following char
if(format[pos] == __scanf_peek( in )) {
__scanf_in( in );
pos++;
}
else return validrets; // else we return the number of valid read
}
pos++;
}
__scanf_end( in );
return validrets;
}

18
src/stdio/sscanf.c Normal file
View file

@ -0,0 +1,18 @@
#include <stdio.h>
#include <fxlibc/scanf.h>
int sscanf(const char * restrict str, char const * restrict fmt, ...)
{
/* This is valid even if str=NULL. */
struct __scanf_input in = {
.str = str,
};
va_list args;
va_start(args, fmt);
int count = __scanf(&in, fmt, &args);
va_end(args);
return count;
}

11
src/stdio/vfscanf.c Normal file
View file

@ -0,0 +1,11 @@
#include <stdio.h>
#include <fxlibc/scanf.h>
int vfscanf(FILE * restrict fp, char const * restrict fmt, va_list args)
{
struct __scanf_input in = {
.fp = fp,
};
return __scanf(&in, fmt, &args);
}

11
src/stdio/vscanf.c Normal file
View file

@ -0,0 +1,11 @@
#include <stdio.h>
#include <fxlibc/scanf.h>
int vscanf(char const * restrict fmt, va_list args)
{
struct __scanf_input in = {
.fp = stdin,
};
return __scanf(&in, fmt, &args);
}

12
src/stdio/vsscanf.c Normal file
View file

@ -0,0 +1,12 @@
#include <stdio.h>
#include <fxlibc/scanf.h>
int vsscanf(const char * restrict str, char const * restrict fmt, va_list args)
{
/* This is valid even if str=NULL. */
struct __scanf_input in = {
.str = str,
};
return __scanf(&in, fmt, &args);
}

View file

@ -1,4 +1,4 @@
#include "stdlib_p.h" #include <fxlibc/stdlib_p.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdbool.h> #include <stdbool.h>
@ -126,6 +126,8 @@ static bool expect(struct __scanf_input *input, char const *sequence)
int __strto_fp(struct __scanf_input *input, double *out, float *outf, int __strto_fp(struct __scanf_input *input, double *out, float *outf,
long double *outl) long double *outl)
{ {
input->currentlength = 0;
/* Skip initial whitespace */ /* Skip initial whitespace */
while(isspace(__scanf_peek(input))) __scanf_in(input); while(isspace(__scanf_peek(input))) __scanf_in(input);

View file

@ -1,12 +1,16 @@
#include "stdlib_p.h" #include <fxlibc/stdlib_p.h>
#include <stdlib.h> #include <stdlib.h>
#include <ctype.h> #include <ctype.h>
#include <errno.h> #include <errno.h>
#include <limits.h> #include <limits.h>
#include <stdbool.h>
int __strto_int(struct __scanf_input *input, int base, long *outl, int __strto_int(struct __scanf_input *input, int base, long *outl,
long long *outll, bool use_unsigned) long long *outll, bool use_unsigned)
{ {
input->currentlength = 0;
/* Skip initial whitespace */ /* Skip initial whitespace */
while(isspace(__scanf_peek(input))) __scanf_in(input); while(isspace(__scanf_peek(input))) __scanf_in(input);

View file

@ -1,4 +1,4 @@
#include "stdlib_p.h" #include <fxlibc/stdlib_p.h>
#include <errno.h> #include <errno.h>
double strtod(char const * restrict ptr, char ** restrict endptr) double strtod(char const * restrict ptr, char ** restrict endptr)

View file

@ -1,4 +1,4 @@
#include "stdlib_p.h" #include <fxlibc/stdlib_p.h>
#include <errno.h> #include <errno.h>
float strtof(char const * restrict ptr, char ** restrict endptr) float strtof(char const * restrict ptr, char ** restrict endptr)

View file

@ -1,4 +1,4 @@
#include "stdlib_p.h" #include <fxlibc/stdlib_p.h>
#include <errno.h> #include <errno.h>
long int strtol(char const * restrict ptr, char ** restrict endptr, int base) long int strtol(char const * restrict ptr, char ** restrict endptr, int base)

View file

@ -1,4 +1,4 @@
#include "stdlib_p.h" #include <fxlibc/stdlib_p.h>
#include <errno.h> #include <errno.h>
long double strtold(char const * restrict ptr, char ** restrict endptr) long double strtold(char const * restrict ptr, char ** restrict endptr)

View file

@ -1,4 +1,4 @@
#include "stdlib_p.h" #include <fxlibc/stdlib_p.h>
#include <errno.h> #include <errno.h>
long long int strtoll(char const * restrict ptr, char ** restrict endptr, long long int strtoll(char const * restrict ptr, char ** restrict endptr,

View file

@ -1,4 +1,4 @@
#include "stdlib_p.h" #include <fxlibc/stdlib_p.h>
#include <errno.h> #include <errno.h>
unsigned long int strtoul(char const * restrict ptr, char ** restrict endptr, unsigned long int strtoul(char const * restrict ptr, char ** restrict endptr,

View file

@ -1,4 +1,4 @@
#include "stdlib_p.h" #include <fxlibc/stdlib_p.h>
#include <errno.h> #include <errno.h>
unsigned long long int strtoull(char const * restrict ptr, unsigned long long int strtoull(char const * restrict ptr,