vsscanf: width for float added; %g %e added; libc_test updated
Build system / Check kernel codestyle (pull_request) Successful in 49s
Build system / Build (pull_request) Successful in 10m37s

strtof added to libc
strtold added to libc
This commit is contained in:
Zverrr
2026-04-30 05:10:07 +05:00
parent db3e211f81
commit 3781e66285
9 changed files with 628 additions and 529 deletions
+2
View File
@@ -63,7 +63,9 @@ strtol
srand
rand
qsort
strtof
strtod
strtold
__assert_fail
;____STRING____
memchr
@@ -56,7 +56,10 @@ DLLAPI int rand(void);
DLLAPI void __assert_fail(const char* expr, const char* file, int line, const char* func);
DLLAPI void qsort(void* base0, size_t n, size_t size, int (*compar)(const void*, const void*));
DLLAPI long double strntold(const char* s, char** sret, size_t n);
DLLAPI double strtod(const char* s, char** sret);
DLLAPI long double strtold(const char* s, char** sret);
DLLAPI float strtof(const char* s, char** sret);
DLLAPI double atof(const char* ascii);
DLLAPI int atoi(const char* s);
@@ -69,12 +69,54 @@ int main()
assert(!strcmp(end, ".00 Rub"));
end = NULL;
assert(strtod(start, &end) == 100.0);
double expected_d = 100.0;
double result_d = strtod(start, &end);
assert(result_d == expected_d);
assert(!strcmp(end, " Rub"));
end = NULL;
float expected_f = 100.0f;
float result_f = strtof(start, &end);
assert(result_f == expected_f);
assert(!strcmp(end, " Rub"));
end = NULL;
long double expected_ld = 100.0;
long double result_ld = strtold(start, &end);
assert(result_ld == expected_ld);
assert(!strcmp(end, " Rub"));
char* st3 = "21.3e3Hello World!";
assert(atof(st3) == 21300.0);
char* st4 = "12345";
float fpart;
int ipart;
sscanf(st4, "%3f%d", &fpart, &ipart);
assert(fpart == 123.0);
assert(ipart == 45);
char* st5 = "123.45";
float fval;
sscanf(st5, "%f", &fval);
assert(fval == 123.45f);
double dval;
sscanf(st5, "%lf", &dval);
assert(dval == 123.45);
long double ldval;
sscanf(st5, "%Lf", &ldval);
assert(ldval == 123.45);
float gval;
sscanf(st5, "%g", &gval);
assert(gval == 123.45f);
float eval;
sscanf(st5, "%e", &eval);
assert(eval == 123.45f);
int nums[10] = { 5, 3, 9, 1, 8, 4, 2, 0, 7, 6 };
qsort(nums, 10, sizeof(int), (int (*)(const void*, const void*))comp);
for (int i = 0; i < 10; i++) {
@@ -98,7 +98,10 @@
#include "stdlib/qsort.c"
#include "stdlib/rand.c"
#include "stdlib/realloc.c"
#include "stdlib/strntold.c"
#include "stdlib/strtod.c"
#include "stdlib/strtof.c"
#include "stdlib/strtold.c"
#include "stdlib/strtol.c"
#include "math/acosh.c"
@@ -182,6 +185,8 @@ ksys_dll_t EXPORTS[] = {
{ "rand", &rand },
{ "qsort", &qsort },
{ "strtod", &strtod },
{ "strtof", &strtof },
{ "strtold", &strtold },
{ "__assert_fail", &__assert_fail },
{ "memchr", &memchr },
{ "memcmp", &memcmp },
@@ -1,439 +1,447 @@
/*
* vsscanf.c
*
* vsscanf(), from which the rest of the scanf()
* family is built
*/
#include <ctype.h>
#include <inttypes.h>
#include <limits.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#ifndef LONG_BIT
#define LONG_BIT (CHAR_BIT * sizeof(long))
#endif
enum flags {
FL_SPLAT = 0x01, /* Drop the value, do not assign */
FL_INV = 0x02, /* Character-set with inverse */
FL_WIDTH = 0x04, /* Field width specified */
FL_MINUS = 0x08, /* Negative number */
};
enum ranks {
rank_char = -2,
rank_short = -1,
rank_int = 0,
rank_long = 1,
rank_longlong = 2,
rank_ptr = INT_MAX /* Special value used for pointers */
};
#define MIN_RANK rank_char
#define MAX_RANK rank_longlong
#define INTMAX_RANK rank_longlong
#define SIZE_T_RANK rank_long
#define PTRDIFF_T_RANK rank_long
enum bail {
bail_none = 0, /* No error condition */
bail_eof, /* Hit EOF */
bail_err /* Conversion mismatch */
};
static inline const char* skipspace(const char* p)
{
while (isspace((unsigned char)*p))
p++;
return p;
}
#undef set_bit
static inline void set_bit(unsigned long* bitmap, unsigned int bit)
{
bitmap[bit / LONG_BIT] |= 1UL << (bit % LONG_BIT);
}
#undef test_bit
static inline int test_bit(unsigned long* bitmap, unsigned int bit)
{
return (int)(bitmap[bit / LONG_BIT] >> (bit % LONG_BIT)) & 1;
}
int vsscanf(const char* buffer, const char* format, va_list ap)
{
const char* p = format;
char ch;
unsigned char uc;
const char* q = buffer;
const char* qq;
uintmax_t val = 0;
double val_d = 0.0;
int rank = rank_int; /* Default rank */
unsigned int width = UINT_MAX;
int base;
enum flags flags = 0;
enum {
st_normal, /* Ground state */
st_flags, /* Special flags */
st_width, /* Field width */
st_modifiers, /* Length or conversion modifiers */
st_match_init, /* Initial state of %[ sequence */
st_match, /* Main state of %[ sequence */
st_match_range, /* After - in a %[ sequence */
} state
= st_normal;
char* sarg = NULL; /* %s %c or %[ string argument */
enum bail bail = bail_none;
int sign;
int converted = 0; /* Successful conversions */
unsigned long matchmap[((1 << CHAR_BIT) + (LONG_BIT - 1)) / LONG_BIT];
int matchinv = 0; /* Is match map inverted? */
unsigned char range_start = 0;
(void)sign;
while ((ch = *p++) && !bail) {
switch (state) {
case st_normal:
if (ch == '%') {
state = st_flags;
flags = 0;
rank = rank_int;
width = UINT_MAX;
} else if (isspace((unsigned char)ch)) {
q = skipspace(q);
} else {
if (*q == ch)
q++;
else
bail = bail_err; /* Match failure */
}
break;
case st_flags:
switch (ch) {
case '*':
flags |= FL_SPLAT;
break;
case '0': /* falls-through */
case '1': /* falls-through */
case '2': /* falls-through */
case '3': /* falls-through */
case '4': /* falls-through */
case '5': /* falls-through */
case '6': /* falls-through */
case '7': /* falls-through */
case '8': /* falls-through */
case '9':
width = (ch - '0');
state = st_width;
flags |= FL_WIDTH;
break;
default:
state = st_modifiers;
p--; /* Process this character again */
break;
}
break;
case st_width:
if (ch >= '0' && ch <= '9') {
width = width * 10 + (ch - '0');
} else {
state = st_modifiers;
p--; /* Process this character again */
}
break;
case st_modifiers:
switch (ch) {
/* Length modifiers - nonterminal sequences */
case 'h':
rank--; /* Shorter rank */
break;
case 'l':
rank++; /* Longer rank */
break;
case 'j':
rank = INTMAX_RANK;
break;
case 'z':
rank = SIZE_T_RANK;
break;
case 't':
rank = PTRDIFF_T_RANK;
break;
case 'L':
case 'q':
rank = rank_longlong; /* long double/long long */
break;
default:
/* Output modifiers - terminal sequences */
/* Next state will be normal */
state = st_normal;
/* Canonicalize rank */
if (rank < MIN_RANK)
rank = MIN_RANK;
else if (rank > MAX_RANK)
rank = MAX_RANK;
switch (ch) {
case 'P': /* Upper case pointer */
case 'p': /* Pointer */
rank = rank_ptr;
base = 0;
sign = 0;
goto scan_int;
case 'i': /* Base-independent integer */
base = 0;
sign = 1;
goto scan_int;
case 'd': /* Decimal integer */
base = 10;
sign = 1;
goto scan_int;
case 'o': /* Octal integer */
base = 8;
sign = 0;
goto scan_int;
case 'u': /* Unsigned decimal integer */
base = 10;
sign = 0;
goto scan_int;
case 'x': /* Hexadecimal integer */
case 'X':
base = 16;
sign = 0;
goto scan_int;
case 'n': /* # of characters consumed */
val = (q - buffer);
goto set_integer;
case 'f': /* Float or Double*/
sign = 1;
goto scan_float;
scan_int:
q = skipspace(q);
if (!*q) {
bail = bail_eof;
break;
}
val = strntoumax(q, (char**)&qq, base,
width);
if (qq == q) {
bail = bail_err;
break;
}
q = qq;
if (!(flags & FL_SPLAT))
converted++;
/* fall through */
set_integer:
if (!(flags & FL_SPLAT)) {
switch (rank) {
case rank_char:
*va_arg(ap,
unsigned char*)
= val;
break;
case rank_short:
*va_arg(ap,
unsigned short*)
= val;
break;
case rank_int:
*va_arg(ap,
unsigned int*)
= val;
break;
case rank_long:
*va_arg(ap,
unsigned long*)
= val;
break;
case rank_longlong:
*va_arg(ap,
unsigned long long*)
= val;
break;
case rank_ptr:
*va_arg(ap, void**) = (void*)(uintptr_t)val;
break;
}
}
break;
scan_float:
q = skipspace(q);
if (!*q) {
bail = bail_eof;
break;
}
val_d = strtod(q, (char**)&qq);
if (qq == q) {
bail = bail_err;
break;
}
q = qq;
if (!(flags & FL_SPLAT))
converted++;
set_float:
if (!(flags & FL_SPLAT)) {
if(rank > rank_int) {
*va_arg(ap,
double*)
= val_d;
} else {
*va_arg(ap,
float*)
= (float)val_d;
}
}
break;
case 'c': /* Character */
/* Default width == 1 */
width = (flags & FL_WIDTH) ? width : 1;
if (flags & FL_SPLAT) {
while (width--) {
if (!*q) {
bail = bail_eof;
break;
}
}
} else {
sarg = va_arg(ap, char*);
while (width--) {
if (!*q) {
bail = bail_eof;
break;
}
*sarg++ = *q++;
}
if (!bail)
converted++;
}
break;
case 's': /* String */
uc = 1; /* Anything nonzero */
if (flags & FL_SPLAT) {
while (width-- && (uc = *q) && !isspace(uc)) {
q++;
}
} else {
char* sp;
sp = sarg = va_arg(ap, char*);
while (width-- && (uc = *q) && !isspace(uc)) {
*sp++ = uc;
q++;
}
if (sarg != sp) {
/* Terminate output */
*sp = '\0';
converted++;
}
}
if (!uc)
bail = bail_eof;
break;
case '[': /* Character range */
sarg = (flags & FL_SPLAT) ? NULL
: va_arg(ap, char*);
state = st_match_init;
matchinv = 0;
memset(matchmap, 0, sizeof matchmap);
break;
case '%': /* %% sequence */
if (*q == '%')
q++;
else
bail = bail_err;
break;
default: /* Anything else */
/* Unknown sequence */
bail = bail_err;
break;
}
}
break;
case st_match_init: /* Initial state for %[ match */
if (ch == '^' && !(flags & FL_INV)) {
matchinv = 1;
} else {
set_bit(matchmap, (unsigned char)ch);
state = st_match;
}
break;
case st_match: /* Main state for %[ match */
if (ch == ']') {
goto match_run;
} else if (ch == '-') {
range_start = (unsigned char)ch;
state = st_match_range;
} else {
set_bit(matchmap, (unsigned char)ch);
}
break;
case st_match_range: /* %[ match after - */
if (ch == ']') {
/* - was last character */
set_bit(matchmap, (unsigned char)'-');
goto match_run;
} else {
int i;
for (i = range_start; i < (unsigned char)ch;
i++)
set_bit(matchmap, i);
state = st_match;
}
break;
match_run: /* Match expression finished */
qq = q;
uc = 1; /* Anything nonzero */
while (width && (uc = *q)
&& test_bit(matchmap, uc) ^ matchinv) {
if (sarg)
*sarg++ = uc;
q++;
}
if (q != qq && sarg) {
*sarg = '\0';
converted++;
} else {
bail = bail_err;
}
if (!uc)
bail = bail_eof;
break;
}
}
if (bail == bail_eof && !converted)
converted = -1; /* Return EOF (-1) */
return converted;
}
/*
* vsscanf.c
*
* vsscanf(), from which the rest of the scanf()
* family is built
*/
#include <ctype.h>
#include <inttypes.h>
#include <limits.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#ifndef LONG_BIT
#define LONG_BIT (CHAR_BIT * sizeof(long))
#endif
enum flags {
FL_SPLAT = 0x01, /* Drop the value, do not assign */
FL_INV = 0x02, /* Character-set with inverse */
FL_WIDTH = 0x04, /* Field width specified */
FL_MINUS = 0x08, /* Negative number */
};
enum ranks {
rank_char = -2,
rank_short = -1,
rank_int = 0,
rank_long = 1,
rank_longlong = 2,
rank_ptr = INT_MAX /* Special value used for pointers */
};
#define MIN_RANK rank_char
#define MAX_RANK rank_longlong
#define INTMAX_RANK rank_longlong
#define SIZE_T_RANK rank_long
#define PTRDIFF_T_RANK rank_long
enum bail {
bail_none = 0, /* No error condition */
bail_eof, /* Hit EOF */
bail_err /* Conversion mismatch */
};
static inline const char* skipspace(const char* p)
{
while (isspace((unsigned char)*p))
p++;
return p;
}
#undef set_bit
static inline void set_bit(unsigned long* bitmap, unsigned int bit)
{
bitmap[bit / LONG_BIT] |= 1UL << (bit % LONG_BIT);
}
#undef test_bit
static inline int test_bit(unsigned long* bitmap, unsigned int bit)
{
return (int)(bitmap[bit / LONG_BIT] >> (bit % LONG_BIT)) & 1;
}
int vsscanf(const char* buffer, const char* format, va_list ap)
{
const char* p = format;
char ch;
unsigned char uc;
const char* q = buffer;
const char* qq;
uintmax_t val = 0;
long double val_ld = 0.0;
int rank = rank_int; /* Default rank */
unsigned int width = UINT_MAX;
int base;
enum flags flags = 0;
enum {
st_normal, /* Ground state */
st_flags, /* Special flags */
st_width, /* Field width */
st_modifiers, /* Length or conversion modifiers */
st_match_init, /* Initial state of %[ sequence */
st_match, /* Main state of %[ sequence */
st_match_range, /* After - in a %[ sequence */
} state
= st_normal;
char* sarg = NULL; /* %s %c or %[ string argument */
enum bail bail = bail_none;
int sign;
int converted = 0; /* Successful conversions */
unsigned long matchmap[((1 << CHAR_BIT) + (LONG_BIT - 1)) / LONG_BIT];
int matchinv = 0; /* Is match map inverted? */
unsigned char range_start = 0;
(void)sign;
while ((ch = *p++) && !bail) {
switch (state) {
case st_normal:
if (ch == '%') {
state = st_flags;
flags = 0;
rank = rank_int;
width = UINT_MAX;
} else if (isspace((unsigned char)ch)) {
q = skipspace(q);
} else {
if (*q == ch)
q++;
else
bail = bail_err; /* Match failure */
}
break;
case st_flags:
switch (ch) {
case '*':
flags |= FL_SPLAT;
break;
case '0': /* falls-through */
case '1': /* falls-through */
case '2': /* falls-through */
case '3': /* falls-through */
case '4': /* falls-through */
case '5': /* falls-through */
case '6': /* falls-through */
case '7': /* falls-through */
case '8': /* falls-through */
case '9':
width = (ch - '0');
state = st_width;
flags |= FL_WIDTH;
break;
default:
state = st_modifiers;
p--; /* Process this character again */
break;
}
break;
case st_width:
if (ch >= '0' && ch <= '9') {
width = width * 10 + (ch - '0');
} else {
state = st_modifiers;
p--; /* Process this character again */
}
break;
case st_modifiers:
switch (ch) {
/* Length modifiers - nonterminal sequences */
case 'h':
rank--; /* Shorter rank */
break;
case 'l':
rank++; /* Longer rank */
break;
case 'j':
rank = INTMAX_RANK;
break;
case 'z':
rank = SIZE_T_RANK;
break;
case 't':
rank = PTRDIFF_T_RANK;
break;
case 'L':
case 'q':
rank = rank_longlong; /* long double/long long */
break;
default:
/* Output modifiers - terminal sequences */
/* Next state will be normal */
state = st_normal;
/* Canonicalize rank */
if (rank < MIN_RANK)
rank = MIN_RANK;
else if (rank > MAX_RANK)
rank = MAX_RANK;
switch (ch) {
case 'P': /* Upper case pointer */
case 'p': /* Pointer */
rank = rank_ptr;
base = 0;
sign = 0;
goto scan_int;
case 'i': /* Base-independent integer */
base = 0;
sign = 1;
goto scan_int;
case 'd': /* Decimal integer */
base = 10;
sign = 1;
goto scan_int;
case 'o': /* Octal integer */
base = 8;
sign = 0;
goto scan_int;
case 'u': /* Unsigned decimal integer */
base = 10;
sign = 0;
goto scan_int;
case 'x': /* Hexadecimal integer */
case 'X':
base = 16;
sign = 0;
goto scan_int;
case 'n': /* # of characters consumed */
val = (q - buffer);
goto set_integer;
case 'f': /* Float or Double*/
case 'e':
case 'g':
sign = 1;
goto scan_float;
scan_int:
q = skipspace(q);
if (!*q) {
bail = bail_eof;
break;
}
val = strntoumax(q, (char**)&qq, base,
width);
if (qq == q) {
bail = bail_err;
break;
}
q = qq;
if (!(flags & FL_SPLAT))
converted++;
/* fall through */
set_integer:
if (!(flags & FL_SPLAT)) {
switch (rank) {
case rank_char:
*va_arg(ap,
unsigned char*)
= val;
break;
case rank_short:
*va_arg(ap,
unsigned short*)
= val;
break;
case rank_int:
*va_arg(ap,
unsigned int*)
= val;
break;
case rank_long:
*va_arg(ap,
unsigned long*)
= val;
break;
case rank_longlong:
*va_arg(ap,
unsigned long long*)
= val;
break;
case rank_ptr:
*va_arg(ap, void**) = (void*)(uintptr_t)val;
break;
}
}
break;
scan_float:
q = skipspace(q);
if (!*q) {
bail = bail_eof;
break;
}
val_ld = strntold(q, (char**)&qq, width);
if (qq == q) {
bail = bail_err;
break;
}
q = qq;
if (!(flags & FL_SPLAT))
converted++;
set_float:
if (!(flags & FL_SPLAT)) {
switch (rank) {
case rank_long:
*va_arg(ap, double*)
= val_ld;
break;
case rank_longlong:
*va_arg(ap, long double*)
= val_ld;
break;
case rank_int:
default:
*va_arg(ap, float*)
= val_ld;
break;
}
}
break;
case 'c': /* Character */
/* Default width == 1 */
width = (flags & FL_WIDTH) ? width : 1;
if (flags & FL_SPLAT) {
while (width--) {
if (!*q) {
bail = bail_eof;
break;
}
}
} else {
sarg = va_arg(ap, char*);
while (width--) {
if (!*q) {
bail = bail_eof;
break;
}
*sarg++ = *q++;
}
if (!bail)
converted++;
}
break;
case 's': /* String */
uc = 1; /* Anything nonzero */
if (flags & FL_SPLAT) {
while (width-- && (uc = *q) && !isspace(uc)) {
q++;
}
} else {
char* sp;
sp = sarg = va_arg(ap, char*);
while (width-- && (uc = *q) && !isspace(uc)) {
*sp++ = uc;
q++;
}
if (sarg != sp) {
/* Terminate output */
*sp = '\0';
converted++;
}
}
if (!uc)
bail = bail_eof;
break;
case '[': /* Character range */
sarg = (flags & FL_SPLAT) ? NULL
: va_arg(ap, char*);
state = st_match_init;
matchinv = 0;
memset(matchmap, 0, sizeof matchmap);
break;
case '%': /* %% sequence */
if (*q == '%')
q++;
else
bail = bail_err;
break;
default: /* Anything else */
/* Unknown sequence */
bail = bail_err;
break;
}
}
break;
case st_match_init: /* Initial state for %[ match */
if (ch == '^' && !(flags & FL_INV)) {
matchinv = 1;
} else {
set_bit(matchmap, (unsigned char)ch);
state = st_match;
}
break;
case st_match: /* Main state for %[ match */
if (ch == ']') {
goto match_run;
} else if (ch == '-') {
range_start = (unsigned char)ch;
state = st_match_range;
} else {
set_bit(matchmap, (unsigned char)ch);
}
break;
case st_match_range: /* %[ match after - */
if (ch == ']') {
/* - was last character */
set_bit(matchmap, (unsigned char)'-');
goto match_run;
} else {
int i;
for (i = range_start; i < (unsigned char)ch;
i++)
set_bit(matchmap, i);
state = st_match;
}
break;
match_run: /* Match expression finished */
qq = q;
uc = 1; /* Anything nonzero */
while (width && (uc = *q)
&& test_bit(matchmap, uc) ^ matchinv) {
if (sarg)
*sarg++ = uc;
q++;
}
if (q != qq && sarg) {
*sarg = '\0';
converted++;
} else {
bail = bail_err;
}
if (!uc)
bail = bail_eof;
break;
}
}
if (bail == bail_eof && !converted)
converted = -1; /* Return EOF (-1) */
return converted;
}
@@ -0,0 +1,109 @@
/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
#include <math.h>
#include <stddef.h>
#ifndef unconst
#define unconst(__v, __t) __extension__({union { const __t __cp; __t __p; } __q; __q.__cp = __v; __q.__p; })
#endif
long double strntold(const char* s, char** sret, size_t n)
{
long double r; /* result */
int e; /* exponent */
long double d; /* scale */
int sign; /* +- 1.0 */
int esign;
int i;
int flags = 0;
r = 0.0;
sign = 1.0;
e = 0;
esign = 1;
while (((*s == ' ') || (*s == '\t')) && n)
{
s++;
n--;
}
if (n)
{
if (*s == '+')
{
s++;
n--;
}
else if (*s == '-') {
sign = -1;
s++;
n--;
}
}
while ((*s >= '0') && (*s <= '9') && n) {
flags |= 1;
r *= 10.0;
r += *s - '0';
s++;
n--;
}
if (*s == '.' && n) {
d = 0.1L;
s++;
n--;
while ((*s >= '0') && (*s <= '9') && n) {
flags |= 2;
r += d * (*s - '0');
s++;
d *= 0.1L;
n--;
}
}
if (flags == 0) {
if (sret)
*sret = unconst(s, char*);
return 0;
}
if (((*s == 'e') || (*s == 'E')) && n) {
s++;
n--;
if (*s == '+' & n)
{
s++;
n--;
}
else if (*s == '-' & n) {
s++;
esign = -1;
n--;
}
if ((*s < '0') || (*s > '9') || !n) {
if (sret)
*sret = unconst(s, char*);
return r;
}
while ((*s >= '0') && (*s <= '9') && n) {
e *= 10;
e += *s - '0';
s++;
n--;
}
}
if (esign < 0)
for (i = 1; i <= e; i++)
r *= 0.1L;
else
for (i = 1; i <= e; i++)
r *= 10.0;
if (sret)
*sret = unconst(s, char*);
return r * sign;
}
@@ -1,89 +1,7 @@
/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
#include <math.h>
#ifndef unconst
#define unconst(__v, __t) __extension__({union { const __t __cp; __t __p; } __q; __q.__cp = __v; __q.__p; })
#endif
double strtod(const char* s, char** sret)
{
long double r; /* result */
int e; /* exponent */
long double d; /* scale */
int sign; /* +- 1.0 */
int esign;
int i;
int flags = 0;
r = 0.0;
sign = 1.0;
e = 0;
esign = 1;
while ((*s == ' ') || (*s == '\t'))
s++;
if (*s == '+')
s++;
else if (*s == '-') {
sign = -1;
s++;
}
while ((*s >= '0') && (*s <= '9')) {
flags |= 1;
r *= 10.0;
r += *s - '0';
s++;
}
if (*s == '.') {
d = 0.1L;
s++;
while ((*s >= '0') && (*s <= '9')) {
flags |= 2;
r += d * (*s - '0');
s++;
d *= 0.1L;
}
}
if (flags == 0) {
if (sret)
*sret = unconst(s, char*);
return 0;
}
if ((*s == 'e') || (*s == 'E')) {
s++;
if (*s == '+')
s++;
else if (*s == '-') {
s++;
esign = -1;
}
if ((*s < '0') || (*s > '9')) {
if (sret)
*sret = unconst(s, char*);
return r;
}
while ((*s >= '0') && (*s <= '9')) {
e *= 10;
e += *s - '0';
s++;
}
}
if (esign < 0)
for (i = 1; i <= e; i++)
r *= 0.1L;
else
for (i = 1; i <= e; i++)
r *= 10.0;
if (sret)
*sret = unconst(s, char*);
return r * sign;
}
/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
#include <limits.h>
double strtod(const char* s, char** sret)
{
return strntold(s, sret, UINT_MAX);
}
@@ -0,0 +1,6 @@
#include<limits.h>
float strtof(const char* s, char** sret)
{
return strntold(s, sret, UINT_MAX);
}
@@ -0,0 +1,6 @@
#include<limits.h>
long double strtold(const char* s, char** sret)
{
return strntold(s, sret, UINT_MAX);
}