Compare commits

..

1 Commits

Author SHA1 Message Date
Heath Mitchell 4ade93eb6f Change dependency 2023-06-27 21:03:17 +02:00
22 changed files with 60 additions and 548 deletions

View File

@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.15)
project(FxLibc VERSION 1.5.0 LANGUAGES C ASM)
project(FxLibc VERSION 1.4.5 LANGUAGES C ASM)
set(CMAKE_INSTALL_MESSAGE LAZY)
@ -124,7 +124,6 @@ set(SOURCES
src/stdio/fputs.c
src/stdio/fread.c
src/stdio/freopen.c
src/stdio/fscanf.c
src/stdio/fseek.c
src/stdio/fsetpos.c
src/stdio/ftell.c
@ -146,24 +145,19 @@ set(SOURCES
src/stdio/puts.c
src/stdio/remove.c
src/stdio/rewind.c
src/stdio/scanf.c
src/stdio/scanf/scan.c
src/stdio/setbuf.c
src/stdio/setvbuf.c
src/stdio/snprintf.c
src/stdio/sprintf.c
src/stdio/sscanf.c
src/stdio/streams.c
src/stdio/ungetc.c
src/stdio/vasprintf.c
src/stdio/vdprintf.c
src/stdio/vfprintf.c
src/stdio/vfscanf.c
src/stdio/vprintf.c
src/stdio/vscanf.c
src/stdio/vsnprintf.c
src/stdio/vsprintf.c
src/stdio/vsscanf.c
# stdlib
src/stdlib/abort.c
src/stdlib/abs.c

12
STATUS
View File

@ -102,19 +102,19 @@ TEST: Function/symbol/macro needs to be tested
(EXT) fileno -
7.19.6.1 fprintf -
7.19.6.2 fscanf TEST
7.19.6.2 fscanf TODO
7.19.6.3 printf -
7.19.6.4 scanf TEST
7.19.6.4 scanf TODO
7.19.6.5 snprintf -
7.19.6.6 sprintf -
7.19.6.7 sscanf TEST
7.19.6.7 sscanf TODO
7.19.6.8 vfprintf -
7.19.6.9 vfscanf TEST
7.19.6.9 vfscanf TODO
7.19.6.10 vprintf -
7.19.6.11 vscanf TEST
7.19.6.11 vscanf TODO
7.19.6.12 vsnprintf -
7.19.6.13 vsprintf -
7.19.6.14 vsscanf TEST
7.19.6.14 vsscanf TODO
(EXT) asprintf -
(EXT) vasprintf -
(EXT) dprintf -

View File

@ -1,4 +1,4 @@
# giteapc: version=1 depends=Lephenixnoir/sh-elf-gcc,Lephenixnoir/OpenLibm
# giteapc: version=1 depends=Heath123/sh-elf-gcc,Heath123/OpenLibm
-include giteapc-config.make

View File

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

View File

@ -59,8 +59,6 @@ void __printf_format_s(
size_t len = 0;
uint32_t precision = opt->precision ? opt->precision : (-1);
while(s[len] && len < precision) len++;
/* Cap precision to real value for __printf_compute_geometry() */
opt->precision = len;
struct __printf_geometry g = {
.prefix = 0, .sign = 0, .content = len,

View File

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

View File

@ -1,366 +1,37 @@
#include <stdio.h>
#include "../stdio_p.h"
#include "../../stdlib/stdlib_p.h"
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdbool.h>
/* Features of this implementation:
- Specifiers:
* Integers (%i, %d, %o, %u, %x, %X)
* Floating-point numbers (%e, %f, %F, %g, %a)
* Strings (%c, %s, %[])
* Pointers (%p)
* Total number of bytes read so far (%n)
- Integer size modifiers: hh, h, l, ll, L, j, z, t. Supported for all
integer conversions, i.e. %i, %d, %u, %o, %x, %X and %n.
- Floating-point size modifiers: l, L for %a, %e, %f, %g.
- Assignment suppression character '*'.
- Maximum field width (but buggy for floating-point, see below).
NOT SUPPORTED:
- Wide characters: %lc, %ls.
- q size modifier.
- "'" (quote) specifier for locale-specific thousand separators.
- String allocation: %mc, %ms.
- Out-of-order assignments "%n$".
- TODO: Maximum field width for floating-point is mostly untested and likely
has bugs when the field ends in the middle of the number. */
void __scanf_start(struct __scanf_input *in)
void __scanf_start(struct __scanf_input *__in)
{
if(in->fp)
in->buffer = fgetc(in->fp);
if(__in->fp)
__in->buffer = fgetc(__in->fp);
else {
in->buffer = (*in->str ? *in->str : EOF);
in->str += (in->buffer != EOF);
__in->buffer = *__in->str;
__in->str += (__in->buffer != 0);
}
}
int __scanf_fetch(struct __scanf_input *in)
int __scanf_fetch(struct __scanf_input *__in)
{
if(in->fp)
return fgetc(in->fp);
if(__in->fp)
return fgetc(__in->fp);
int c = *in->str;
int c = *__in->str;
if(c == 0)
return EOF;
in->str++;
__in->str++;
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;
if(in->fp)
ungetc(in->buffer, in->fp);
if(__in->fp)
ungetc(__in->buffer, __in->fp);
else
in->str--;
}
static void __skip_spaces(struct __scanf_input *in)
{
while(isspace(__scanf_peek(in)))
__scanf_in(in);
}
static void __scanf_store_i(int64_t value, int size, va_list *args)
{
if(size == 1)
*va_arg(*args, int8_t *) = value;
else if(size == 2)
*va_arg(*args, int16_t *) = value;
else if(size == 4)
*va_arg(*args, int32_t *) = value;
else if(size == 8)
*va_arg(*args, int64_t *) = value;
}
static void __scanf_store_d(long double value, int size, va_list *args)
{
if(size == sizeof(float))
*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;
}
struct scanf_format {
/* Maximum field width */
int field_width;
/* Size of the assigned (integer or floating-point) type, in bytes */
uint8_t size;
/* Whether to skip assignment */
bool skip;
/* Set of bytes allowed for bracket sets in %[] */
uint8_t bracket_set[32];
};
/* Allow/disallow the entire set */
static void bracket_set_init(uint8_t *set, bool allow)
{
memset(set, allow ? 0xff : 0x00, 32);
}
/* Allow/disallow a range of characters. Both ends are included. */
static void bracket_set_range(
uint8_t *set, uint8_t start, uint8_t end, bool allow)
{
for(int u = start; u <= end; u++) {
int byte = u >> 3;
int bit = 1 << (u & 7);
if(allow)
set[byte] |= bit;
else
set[byte] &= ~bit;
}
}
/* Check whether a byte is allowed by the bracket set. */
static bool bracket_set_test(uint8_t *set, int c)
{
return (c != EOF) && (set[c >> 3] & (1 << (c & 7)));
}
/* Parse a bracket set from a format string. Returns true on success. */
static bool bracket_set_parse(uint8_t *set, char const *format, int *pos)
{
int last = 0;
bool allow = true;
bracket_set_init(set, false);
/* '^' denotes a negated set */
if(format[*pos] == '^') {
allow = false;
(*pos)++;
bracket_set_init(set, true);
}
/* ']' as the first character adds ']' to the set */
if(format[*pos] == ']' ) {
bracket_set_range(set, ']', ']', allow);
(*pos)++;
}
for(; format[*pos] && format[*pos] != ']'; (*pos)++) {
/* '-' as the last character, thus explicitly in the set */
if(format[*pos] == '-' && format[*pos + 1] == ']')
bracket_set_range(set, '-', '-', allow);
/* '-' as denoting a range */
else if(format[*pos] == '-') {
(*pos)++;
bracket_set_range(set, last, format[*pos], allow);
}
/* Any other character */
else {
last = format[*pos];
bracket_set_range(set, last, last, allow);
}
}
return (format[*pos] == ']');
}
/* Parse a format in the format string. Returns specifier, 0 on error. */
static int parse_fmt(char const *fmt, int *pos, struct scanf_format *opt)
{
opt->field_width = INT_MAX;
opt->size = sizeof(int);
opt->skip = false;
int width = 0;
char size_letter = 0;
for((*pos)++;; (*pos)++) {
int c = fmt[*pos];
if(c == '*')
opt->skip = true;
else if(strchr("hlzjtL", c)) {
if(c == 'h')
opt->size = (size_letter=='h') ? sizeof(char) : sizeof(short);
else if(c == 'l')
opt->size = (size_letter=='l') ? sizeof(long long) :
sizeof(long);
else if(c == 'z')
opt->size = sizeof(size_t);
else if(c == 'j')
opt->size = sizeof(intmax_t);
else if(c == 't')
opt->size = sizeof(ptrdiff_t);
else if(c == 'L')
opt->size = sizeof(long double);
size_letter = c;
}
else if(isdigit(c)) {
width = width * 10 + (fmt[*pos] - '0');
opt->field_width = width;
}
else if(c == '[') {
(*pos)++;
return bracket_set_parse(opt->bracket_set, fmt, pos) ? '[' : 0;
}
else if(strchr("diouxXpsn", c))
return c;
else if(strchr("aAeEfFgG", c)) {
/* Adjust interpretation of no size / 'l' size */
if(size_letter == 0)
opt->size = sizeof(float);
if(size_letter == 'l')
opt->size = sizeof(double);
return c;
}
else if(c == 'c') {
if(opt->field_width == INT_MAX)
opt->field_width = 1;
return c;
}
else return 0;
}
return 0;
}
int __scanf(
struct __scanf_input * __restrict__ in,
char const * __restrict__ format,
va_list *args)
{
/* Number of successful assignments */
int validrets = 0;
for(int pos = 0; format[pos]; pos++) {
if(format[pos] == ' ') {
__skip_spaces(in);
continue;
}
else if(format[pos] != '%' || format[pos + 1] == '%') {
/* Expect this specific character */
if(__scanf_peek(in) != format[pos])
return validrets;
__scanf_in(in);
pos += (format[pos] == '%');
continue;
}
/* Perform a conversion */
struct scanf_format opt;
int spec = parse_fmt(format, &pos, &opt);
if(spec == 0)
return validrets;
switch(spec) {
case '[': {
char *c = opt.skip ? NULL : va_arg(*args, char *);
int i;
for(i = 0; i < opt.field_width; i++) {
int temp = __scanf_peek(in);
if(bracket_set_test(opt.bracket_set, temp)) {
__scanf_in(in);
if(c) *c++ = temp;
}
else if(temp==EOF && !i && !validrets)
return EOF;
else break;
}
if(!i)
return validrets;
*c = '\0';
validrets += !opt.skip;
break;
}
case 'n':
__scanf_store_i(in->bytes_read, opt.size, args);
break;
case 'd':
case 'i':
case 'o':
case 'u':
case 'x':
case 'X': {
int f = format[pos];
int base = (f == 'd' || f == 'u') ? 10 :
(f == 'o') ? 8:
(f == 'x' || f == 'X') ? 16 : 0;
bool use_unsigned = (f == 'o' || f == 'x' || f == 'X');
long long int temp;
int err = __strto_int(in, base, NULL, &temp, use_unsigned,
opt.field_width);
if(err == EOF && validrets == 0) return EOF;
if(err) return validrets;
if(!opt.skip)
__scanf_store_i(temp, opt.size, args);
validrets++;
break;
}
case 'a':
case 'A':
case 'e':
case 'E':
case 'f':
case 'F':
case 'g':
case 'G': {
long double temp;
int err = __strto_fp(in, NULL, NULL, &temp, opt.field_width);
if(err == EOF && validrets == 0) return EOF;
if(err) return validrets;
if(!opt.skip)
__scanf_store_d(temp, opt.size, args);
validrets++;
break;
}
case 'p': {
void *p = opt.skip ? NULL : va_arg(*args, void *);
_Static_assert(sizeof(p) == sizeof(long));
int err = __strto_int(in, 0, p, NULL, true, opt.field_width);
if(err) return validrets;
validrets += !opt.skip;
break;
}
case 'c': {
char *c = opt.skip ? NULL : va_arg(*args, char *);
for(int u = 0; u < opt.field_width; u++) {
int temp = __scanf_in(in);
if(temp==EOF) return EOF;
else if(c) *c++ = temp;
}
validrets += !opt.skip;
break;
}
case 's': {
char *c = opt.skip ? NULL : va_arg(*args, char *);
__skip_spaces(in);
for(int i = 0; i < opt.field_width; i++) {
int temp = __scanf_peek(in);
if(temp==EOF && !i) return validrets;
if(isspace(temp) || temp==EOF) {
if(c) {
*c = 0;
validrets++;
}
break;
}
else {
int temp = __scanf_in(in);
if(c) *c++ = temp;
}
}
break;
}
}
}
return validrets;
__in->str--;
}

View File

@ -1,19 +0,0 @@
#include <stdio.h>
#include "stdio_p.h"
int sscanf(const char * restrict str, char const * restrict fmt, ...)
{
struct __scanf_input in = {
.str = str,
};
va_list args;
va_start(args, fmt);
__scanf_start(&in);
int count = __scanf(&in, fmt, &args);
__scanf_end(&in);
va_end(args);
return count;
}

View File

@ -2,7 +2,6 @@
# define __STDIO_P_H__
#include <stdio.h>
#include <stdbool.h>
/*
** General utilities for scanf(); we expose them here as we use subfunctions of
@ -17,21 +16,9 @@
struct __scanf_input {
char const * __restrict__ str;
FILE *fp;
/* Single-character lookahead buffer */
int buffer;
/* Total numbers of bytes read in a scall to *scanf() */
int bytes_read;
};
/* 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. */
void __scanf_start(struct __scanf_input *__in);
@ -43,17 +30,9 @@ static inline int __scanf_in(struct __scanf_input *__in)
{
int c = __in->buffer;
__in->buffer = __scanf_fetch(__in);
__in->bytes_read++;
return c;
}
/* Read the next byte and also decrease a total count of available reads. */
static inline int __scanf_in_limit(struct __scanf_input *__in, int *__N)
{
(*__N)--;
return __scanf_in(__in);
}
/* Peek the next byte without advancing. */
static inline int __scanf_peek(struct __scanf_input *__in)
{

View File

@ -1,14 +0,0 @@
#include <stdio.h>
#include "stdio_p.h"
int vfscanf(FILE * restrict fp, char const * restrict fmt, va_list args)
{
struct __scanf_input in = {
.fp = fp,
};
__scanf_start(&in);
int rc = __scanf(&in, fmt, &args);
__scanf_end(&in);
return rc;
}

View File

@ -1,14 +0,0 @@
#include <stdio.h>
#include "stdio_p.h"
int vscanf(char const * restrict fmt, va_list args)
{
struct __scanf_input in = {
.fp = stdin,
};
__scanf_start(&in);
int rc = __scanf(&in, fmt, &args);
__scanf_end(&in);
return rc;
}

View File

@ -1,15 +0,0 @@
#include <stdio.h>
#include "stdio_p.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,
};
__scanf_start(&in);
int rc = __scanf(&in, fmt, &args);
__scanf_end(&in);
return rc;
}

View File

@ -3,7 +3,6 @@
#include <stdlib.h>
#include <stdbool.h>
#include <limits.h>
#include "../stdio/stdio_p.h"
/*
@ -23,17 +22,13 @@
** On platforms where long is 32-bit, 64-bit operations are performed only if
** outll is non-NULL. This is because multiplications with overflow can be
** expensive.
**
** N is the bound on the number of characters to read. To disable the bound,
** specify INT_MAX.
*/
int __strto_int(
struct __scanf_input *__input,
int __base,
long *__outl,
long long *__outll,
bool __use_unsigned,
int __N);
bool __use_unsigned);
/*
** Parse a floating-point value from a string. This is the base function for
@ -47,7 +42,6 @@ int __strto_fp(
struct __scanf_input *__input,
double *__out,
float *__outf,
long double *__outl,
int __N);
long double *__outl);
#endif /*__STDLIB_P_H__*/

View File

@ -38,8 +38,8 @@
** -> In hexadecimal notation, we read as many bits as the mantissa of a long
** double, then later multiply by a power of 2. There are no approximations.
*/
static int parse_digits(struct __scanf_input *input,
SIGNIFICAND_TYPE *digits, long *exponent, bool hexadecimal, int *N)
static bool parse_digits(struct __scanf_input *input,
SIGNIFICAND_TYPE *digits, long *exponent, bool hexadecimal)
{
bool dot_found = false;
int digits_found=0, c=0;
@ -53,14 +53,12 @@ static int parse_digits(struct __scanf_input *input,
int dot_character = '.';
int exp_character = (hexadecimal ? 'p' : 'e');
for(int i = 0; *N >= 0; i++) {
for(int i = 0; true; i++) {
c = __scanf_peek(input);
if(i == 0 && c == EOF)
return EOF;
if(!(isdigit(c) ||
(hexadecimal && isxdigit(c)) ||
(c == dot_character && !dot_found))) break;
__scanf_in_limit(input, N);
__scanf_in(input);
if(c == dot_character) {
dot_found = true;
@ -104,10 +102,9 @@ static int parse_digits(struct __scanf_input *input,
set correctly */
struct __scanf_input backup = *input;
__scanf_in_limit(input, N);
__scanf_in(input);
long e = 0;
// TODO: strto_fp: Pass limit to __strto_int
if(__strto_int(input, 10, &e, NULL, false, *N) == 0)
if(__strto_int(input, 10, &e, NULL, false) == 0)
*exponent += e;
else
*input = backup;
@ -127,21 +124,16 @@ static bool expect(struct __scanf_input *input, char const *sequence)
}
int __strto_fp(struct __scanf_input *input, double *out, float *outf,
long double *outl, int N)
long double *outl)
{
/* Skip initial whitespace */
while(isspace(__scanf_peek(input))) __scanf_in(input);
// TODO: strto_fp() doesn't support size limits well, affecting %5f etc.
if(N <= 0)
return EOF;
/* Read optional sign */
bool negative = false;
int sign = __scanf_peek(input);
if(sign == '-') negative = true;
if(sign == '-' || sign == '+') __scanf_in_limit(input, &N);
if(sign == '-' || sign == '+') __scanf_in(input);
int errno_value = 0;
bool valid = false;
@ -162,10 +154,8 @@ int __strto_fp(struct __scanf_input *input, double *out, float *outf,
if(__scanf_peek(input) == '(') {
while(i < 31) {
int c = __scanf_in_limit(input, &N);
int c = __scanf_in(input);
if(c == ')') break;
if(c == EOF || N <= 0)
return EOF;
arg[i++] = c;
}
arg[i] = 0;
@ -187,9 +177,6 @@ int __strto_fp(struct __scanf_input *input, double *out, float *outf,
if(outl) *outl = __builtin_infl();
valid = true;
}
else if(__scanf_peek(input) == EOF) {
return EOF;
}
else {
SIGNIFICAND_TYPE digits = 0;
long e = 0;
@ -198,9 +185,9 @@ int __strto_fp(struct __scanf_input *input, double *out, float *outf,
not 0x isn't a problem. */
bool hexa = false;
if(__scanf_peek(input) == '0') {
__scanf_in_limit(input, &N);
__scanf_in(input);
if(tolower(__scanf_peek(input)) == 'x') {
__scanf_in_limit(input, &N);
__scanf_in(input);
hexa = true;
}
/* Count the 0 as a digit */
@ -208,19 +195,13 @@ int __strto_fp(struct __scanf_input *input, double *out, float *outf,
}
if(hexa) {
int rc = parse_digits(input, &digits, &e, true, &N);
if(!valid && rc == EOF)
return EOF;
valid |= rc;
valid |= parse_digits(input, &digits, &e, true);
if(out) *out = (double)digits * exp2(e);
if(outf) *outf = (float)digits * exp2f(e);
if(outl) *outl = (long double)digits * exp2l(e);
}
else {
int rc = parse_digits(input, &digits, &e, false, &N);
if(!valid && rc == EOF)
return EOF;
valid |= rc;
valid |= parse_digits(input, &digits, &e, false);
if(out) *out = (double)digits * pow(10, e);
if(outf) *outf = (float)digits * powf(10, e);
if(outl) *outl = (long double)digits * powl(10, e);

View File

@ -5,19 +5,16 @@
#include <limits.h>
int __strto_int(struct __scanf_input *input, int base, long *outl,
long long *outll, bool use_unsigned, int N)
long long *outll, bool use_unsigned)
{
/* Skip initial whitespace */
while(isspace(__scanf_peek(input))) __scanf_in(input);
if(N <= 0)
return EOF;
/* Accept a sign character */
bool negative = false;
int sign = __scanf_peek(input);
if(sign == '-') negative = true;
if(sign == '-' || sign == '+') __scanf_in_limit(input, &N);
if(sign == '-' || sign == '+') __scanf_in(input);
/* Use unsigned variables as only these have defined overflow */
unsigned long xl = 0;
@ -28,10 +25,10 @@ int __strto_int(struct __scanf_input *input, int base, long *outl,
/* Read prefixes and determine base */
if(__scanf_peek(input) == '0') {
__scanf_in_limit(input, &N);
__scanf_in(input);
if((base == 0 || base == 16) &&
tolower(__scanf_peek(input)) == 'x') {
__scanf_in_limit(input, &N);
__scanf_in(input);
base = 16;
}
/* If we don't consume the x then count the 0 as a digit */
@ -39,13 +36,11 @@ int __strto_int(struct __scanf_input *input, int base, long *outl,
if(base == 0)
base = 8;
}
if(!valid && (N <= 0 || __scanf_peek(input) == EOF))
return EOF;
if(base == 0)
base = 10;
/* Read digits */
while(N > 0) {
while(1) {
int v = -1;
int c = __scanf_peek(input);
if(isdigit(c)) v = c - '0';
@ -70,7 +65,7 @@ int __strto_int(struct __scanf_input *input, int base, long *outl,
errno_value = ERANGE;
}
__scanf_in_limit(input, &N);
__scanf_in(input);
}
/* Handle sign and range */

View File

@ -9,11 +9,11 @@ double strtod(char const * restrict ptr, char ** restrict endptr)
struct __scanf_input in = { .str = ptr, .fp = NULL };
__scanf_start(&in);
int err = __strto_fp(&in, &d, NULL, NULL, INT_MAX);
int err = __strto_fp(&in, &d, NULL, NULL);
__scanf_end(&in);
if(err != 0)
errno = (err == EOF) ? EINVAL : err;
errno = err;
if(err != EINVAL && endptr)
*endptr = (char *)in.str;
return d;

View File

@ -9,11 +9,11 @@ float strtof(char const * restrict ptr, char ** restrict endptr)
struct __scanf_input in = { .str = ptr, .fp = NULL };
__scanf_start(&in);
int err = __strto_fp(&in, NULL, &f, NULL, INT_MAX);
int err = __strto_fp(&in, NULL, &f, NULL);
__scanf_end(&in);
if(err != 0)
errno = (err == EOF) ? EINVAL : err;
errno = err;
if(err != EINVAL && endptr)
*endptr = (char *)in.str;
return f;

View File

@ -9,11 +9,11 @@ long int strtol(char const * restrict ptr, char ** restrict endptr, int base)
struct __scanf_input in = { .str = ptr, .fp = NULL };
__scanf_start(&in);
int err = __strto_int(&in, base, &n, NULL, false, INT_MAX);
int err = __strto_int(&in, base, &n, NULL, false);
__scanf_end(&in);
if(err != 0)
errno = (err == EOF) ? EINVAL : err;
errno = err;
if(err != EINVAL && endptr)
*endptr = (char *)in.str;
return n;

View File

@ -9,11 +9,11 @@ long double strtold(char const * restrict ptr, char ** restrict endptr)
struct __scanf_input in = { .str = ptr, .fp = NULL };
__scanf_start(&in);
int err = __strto_fp(&in, NULL, NULL, &ld, INT_MAX);
int err = __strto_fp(&in, NULL, NULL, &ld);
__scanf_end(&in);
if(err != 0)
errno = (err == EOF) ? EINVAL : err;
errno = err;
if(err != EINVAL && endptr)
*endptr = (char *)in.str;
return ld;

View File

@ -10,11 +10,11 @@ long long int strtoll(char const * restrict ptr, char ** restrict endptr,
struct __scanf_input in = { .str = ptr, .fp = NULL };
__scanf_start(&in);
int err = __strto_int(&in, base, NULL, &n, false, INT_MAX);
int err = __strto_int(&in, base, NULL, &n, false);
__scanf_end(&in);
if(err != 0)
errno = (err == EOF) ? EINVAL : err;
errno = err;
if(err != EINVAL && endptr)
*endptr = (char *)in.str;
return n;

View File

@ -10,11 +10,11 @@ unsigned long int strtoul(char const * restrict ptr, char ** restrict endptr,
struct __scanf_input in = { .str = ptr, .fp = NULL };
__scanf_start(&in);
int err = __strto_int(&in, base, (long *)&n, NULL, true, INT_MAX);
int err = __strto_int(&in, base, (long *)&n, NULL, true);
__scanf_end(&in);
if(err != 0)
errno = (err == EOF) ? EINVAL : err;
errno = err;
if(err != EINVAL && endptr)
*endptr = (char *)in.str;
return n;

View File

@ -10,11 +10,11 @@ unsigned long long int strtoull(char const * restrict ptr,
struct __scanf_input in = { .str = ptr, .fp = NULL };
__scanf_start(&in);
int err = __strto_int(&in, base, NULL, (long long *)&n, true, INT_MAX);
int err = __strto_int(&in, base, NULL, (long long *)&n, true);
__scanf_end(&in);
if(err != 0)
errno = (err == EOF) ? EINVAL : err;
errno = err;
if(err != EINVAL && endptr)
*endptr = (char *)in.str;
return n;