1 #include <stdlib.h>
2 #ifdef __wasilibc_unmodified_upstream // Changes to optimize printf/scanf when long double isn't needed
3 #else
4 #include "printscan.h"
5 #define __NEED_locale_t
6 #include <bits/alltypes.h>
7 #endif
8 #include "shgetc.h"
9 #include "floatscan.h"
10 #include "stdio_impl.h"
11 
12 #if defined(__wasilibc_printscan_no_long_double)
strtox(const char * s,char ** p,int prec)13 static long_double strtox(const char *s, char **p, int prec)
14 #else
15 static long double strtox(const char *s, char **p, int prec)
16 #endif
17 {
18 	FILE f;
19 	sh_fromstring(&f, s);
20 	shlim(&f, 0);
21 #if defined(__wasilibc_printscan_no_long_double)
22 	long_double y = __floatscan(&f, prec, 1);
23 #else
24 	long double y = __floatscan(&f, prec, 1);
25 #endif
26 	off_t cnt = shcnt(&f);
27 	if (p) *p = cnt ? (char *)s + cnt : (char *)s;
28 	return y;
29 }
30 
strtof(const char * restrict s,char ** restrict p)31 float strtof(const char *restrict s, char **restrict p)
32 {
33 	return strtox(s, p, 0);
34 }
35 
strtod(const char * restrict s,char ** restrict p)36 double strtod(const char *restrict s, char **restrict p)
37 {
38 	return strtox(s, p, 1);
39 }
40 
strtold(const char * restrict s,char ** restrict p)41 long double strtold(const char *restrict s, char **restrict p)
42 {
43 #if defined(__wasilibc_printscan_no_long_double)
44 	long_double_not_supported();
45 #else
46 	return strtox(s, p, 2);
47 #endif
48 }
49 
50 #ifdef __wasilibc_unmodified_upstream // WASI doesn't support signature-changing aliases
51 weak_alias(strtof, strtof_l);
52 weak_alias(strtod, strtod_l);
53 weak_alias(strtold, strtold_l);
54 weak_alias(strtof, __strtof_l);
55 weak_alias(strtod, __strtod_l);
56 weak_alias(strtold, __strtold_l);
57 #else
58 // WebAssembly doesn't permit signature-changing aliases, so use wrapper
59 // functions instead.
strtof_l(const char * restrict s,char ** restrict p,locale_t loc)60 weak float strtof_l(const char *restrict s, char **restrict p, locale_t loc) {
61 	return strtof(s, p);
62 }
strtod_l(const char * restrict s,char ** restrict p,locale_t loc)63 weak double strtod_l(const char *restrict s, char **restrict p, locale_t loc) {
64 	return strtod(s, p);
65 }
strtold_l(const char * restrict s,char ** restrict p,locale_t loc)66 weak long double strtold_l(const char *restrict s, char **restrict p, locale_t loc) {
67 	return strtold(s, p);
68 }
69 #endif
70