xref: /freebsd/lib/libc/stdlib/strfromf.c (revision f68d7bfc1479042184e09431bd55771c50c47f68)
1*f68d7bfcSFaraz Vahedi /*
2*f68d7bfcSFaraz Vahedi  * Copyright (c) 2026 Faraz Vahedi <kfv@kfv.io>
3*f68d7bfcSFaraz Vahedi  *
4*f68d7bfcSFaraz Vahedi  * SPDX-License-Identifier: BSD-2-Clause
5*f68d7bfcSFaraz Vahedi  */
6*f68d7bfcSFaraz Vahedi 
7*f68d7bfcSFaraz Vahedi #include <ctype.h>
8*f68d7bfcSFaraz Vahedi #include <stdlib.h>
9*f68d7bfcSFaraz Vahedi 
10*f68d7bfcSFaraz Vahedi #include "strfrom.h"
11*f68d7bfcSFaraz Vahedi 
12*f68d7bfcSFaraz Vahedi int
strfromf(char * __restrict s,size_t n,const char * __restrict fmt,float fp)13*f68d7bfcSFaraz Vahedi strfromf(char * __restrict s, size_t n, const char * __restrict fmt, float fp)
14*f68d7bfcSFaraz Vahedi {
15*f68d7bfcSFaraz Vahedi 	char conv, lc, *digits, *dend;
16*f68d7bfcSFaraz Vahedi 	int prec, decpt, signflag, ret, mode, ndig_req;
17*f68d7bfcSFaraz Vahedi 	double dbl;
18*f68d7bfcSFaraz Vahedi 
19*f68d7bfcSFaraz Vahedi 	dbl = (double)fp;
20*f68d7bfcSFaraz Vahedi 	conv = __sf_parse_fmt(fmt, &prec);
21*f68d7bfcSFaraz Vahedi 	if (conv == '\0')
22*f68d7bfcSFaraz Vahedi 		return (__sf_edoofus(s, n));
23*f68d7bfcSFaraz Vahedi 	lc = tolower((unsigned char)conv);
24*f68d7bfcSFaraz Vahedi 
25*f68d7bfcSFaraz Vahedi 	if (lc == 'a') {
26*f68d7bfcSFaraz Vahedi 		digits = __hdtoa(dbl, __sf_xdigits(conv),
27*f68d7bfcSFaraz Vahedi 		    prec >= 0 ? prec + 1 : -1, &decpt, &signflag, &dend);
28*f68d7bfcSFaraz Vahedi 		ret = __sf_render_hex(s, n, conv, prec, digits, dend, decpt,
29*f68d7bfcSFaraz Vahedi 		    signflag);
30*f68d7bfcSFaraz Vahedi 		freedtoa(digits);
31*f68d7bfcSFaraz Vahedi 		return (ret);
32*f68d7bfcSFaraz Vahedi 	}
33*f68d7bfcSFaraz Vahedi 
34*f68d7bfcSFaraz Vahedi 	if (prec < 0)
35*f68d7bfcSFaraz Vahedi 		prec = 6;
36*f68d7bfcSFaraz Vahedi 
37*f68d7bfcSFaraz Vahedi 	__sf_decimal_mode(lc, prec, &mode, &ndig_req);
38*f68d7bfcSFaraz Vahedi 
39*f68d7bfcSFaraz Vahedi 	digits = dtoa(dbl, mode, ndig_req, &decpt, &signflag, &dend);
40*f68d7bfcSFaraz Vahedi 
41*f68d7bfcSFaraz Vahedi 	ret = __sf_render_decimal(s, n, conv, lc, prec, digits, dend, decpt,
42*f68d7bfcSFaraz Vahedi 	    signflag, decpt == 9999);
43*f68d7bfcSFaraz Vahedi 
44*f68d7bfcSFaraz Vahedi 	freedtoa(digits);
45*f68d7bfcSFaraz Vahedi 
46*f68d7bfcSFaraz Vahedi 	return (ret);
47*f68d7bfcSFaraz Vahedi }
48