xref: /aosp_15_r20/external/musl/src/locale/strfmon.c (revision c9945492fdd68bbe62686c5b452b4dc1be3f8453)
1*c9945492SAndroid Build Coastguard Worker #include <stdio.h>
2*c9945492SAndroid Build Coastguard Worker #include <ctype.h>
3*c9945492SAndroid Build Coastguard Worker #include <stdarg.h>
4*c9945492SAndroid Build Coastguard Worker #include <monetary.h>
5*c9945492SAndroid Build Coastguard Worker #include <errno.h>
6*c9945492SAndroid Build Coastguard Worker #include "locale_impl.h"
7*c9945492SAndroid Build Coastguard Worker 
vstrfmon_l(char * s,size_t n,locale_t loc,const char * fmt,va_list ap)8*c9945492SAndroid Build Coastguard Worker static ssize_t vstrfmon_l(char *s, size_t n, locale_t loc, const char *fmt, va_list ap)
9*c9945492SAndroid Build Coastguard Worker {
10*c9945492SAndroid Build Coastguard Worker 	size_t l;
11*c9945492SAndroid Build Coastguard Worker 	double x;
12*c9945492SAndroid Build Coastguard Worker 	int fill, nogrp, negpar, nosym, left, intl;
13*c9945492SAndroid Build Coastguard Worker 	int lp, rp, w, fw;
14*c9945492SAndroid Build Coastguard Worker 	char *s0=s;
15*c9945492SAndroid Build Coastguard Worker 	for (; n && *fmt; ) {
16*c9945492SAndroid Build Coastguard Worker 		if (*fmt != '%') {
17*c9945492SAndroid Build Coastguard Worker 		literal:
18*c9945492SAndroid Build Coastguard Worker 			*s++ = *fmt++;
19*c9945492SAndroid Build Coastguard Worker 			n--;
20*c9945492SAndroid Build Coastguard Worker 			continue;
21*c9945492SAndroid Build Coastguard Worker 		}
22*c9945492SAndroid Build Coastguard Worker 		fmt++;
23*c9945492SAndroid Build Coastguard Worker 		if (*fmt == '%') goto literal;
24*c9945492SAndroid Build Coastguard Worker 
25*c9945492SAndroid Build Coastguard Worker 		fill = ' ';
26*c9945492SAndroid Build Coastguard Worker 		nogrp = 0;
27*c9945492SAndroid Build Coastguard Worker 		negpar = 0;
28*c9945492SAndroid Build Coastguard Worker 		nosym = 0;
29*c9945492SAndroid Build Coastguard Worker 		left = 0;
30*c9945492SAndroid Build Coastguard Worker 		for (; ; fmt++) {
31*c9945492SAndroid Build Coastguard Worker 			switch (*fmt) {
32*c9945492SAndroid Build Coastguard Worker 			case '=':
33*c9945492SAndroid Build Coastguard Worker 				fill = *++fmt;
34*c9945492SAndroid Build Coastguard Worker 				continue;
35*c9945492SAndroid Build Coastguard Worker 			case '^':
36*c9945492SAndroid Build Coastguard Worker 				nogrp = 1;
37*c9945492SAndroid Build Coastguard Worker 				continue;
38*c9945492SAndroid Build Coastguard Worker 			case '(':
39*c9945492SAndroid Build Coastguard Worker 				negpar = 1;
40*c9945492SAndroid Build Coastguard Worker 			case '+':
41*c9945492SAndroid Build Coastguard Worker 				continue;
42*c9945492SAndroid Build Coastguard Worker 			case '!':
43*c9945492SAndroid Build Coastguard Worker 				nosym = 1;
44*c9945492SAndroid Build Coastguard Worker 				continue;
45*c9945492SAndroid Build Coastguard Worker 			case '-':
46*c9945492SAndroid Build Coastguard Worker 				left = 1;
47*c9945492SAndroid Build Coastguard Worker 				continue;
48*c9945492SAndroid Build Coastguard Worker 			}
49*c9945492SAndroid Build Coastguard Worker 			break;
50*c9945492SAndroid Build Coastguard Worker 		}
51*c9945492SAndroid Build Coastguard Worker 
52*c9945492SAndroid Build Coastguard Worker 		for (fw=0; isdigit(*fmt); fmt++)
53*c9945492SAndroid Build Coastguard Worker 			fw = 10*fw + (*fmt-'0');
54*c9945492SAndroid Build Coastguard Worker 		lp = 0;
55*c9945492SAndroid Build Coastguard Worker 		rp = 2;
56*c9945492SAndroid Build Coastguard Worker 		if (*fmt=='#') for (lp=0, fmt++; isdigit(*fmt); fmt++)
57*c9945492SAndroid Build Coastguard Worker 			lp = 10*lp + (*fmt-'0');
58*c9945492SAndroid Build Coastguard Worker 		if (*fmt=='.') for (rp=0, fmt++; isdigit(*fmt); fmt++)
59*c9945492SAndroid Build Coastguard Worker 			rp = 10*rp + (*fmt-'0');
60*c9945492SAndroid Build Coastguard Worker 
61*c9945492SAndroid Build Coastguard Worker 		intl = *fmt++ == 'i';
62*c9945492SAndroid Build Coastguard Worker 
63*c9945492SAndroid Build Coastguard Worker 		w = lp + 1 + rp;
64*c9945492SAndroid Build Coastguard Worker 		if (!left && fw>w) w = fw;
65*c9945492SAndroid Build Coastguard Worker 
66*c9945492SAndroid Build Coastguard Worker 		x = va_arg(ap, double);
67*c9945492SAndroid Build Coastguard Worker 		l = snprintf(s, n, "%*.*f", w, rp, x);
68*c9945492SAndroid Build Coastguard Worker 		if (l >= n) {
69*c9945492SAndroid Build Coastguard Worker 			errno = E2BIG;
70*c9945492SAndroid Build Coastguard Worker 			return -1;
71*c9945492SAndroid Build Coastguard Worker 		}
72*c9945492SAndroid Build Coastguard Worker 		s += l;
73*c9945492SAndroid Build Coastguard Worker 		n -= l;
74*c9945492SAndroid Build Coastguard Worker 	}
75*c9945492SAndroid Build Coastguard Worker 	return s-s0;
76*c9945492SAndroid Build Coastguard Worker }
77*c9945492SAndroid Build Coastguard Worker 
strfmon_l(char * restrict s,size_t n,locale_t loc,const char * restrict fmt,...)78*c9945492SAndroid Build Coastguard Worker ssize_t strfmon_l(char *restrict s, size_t n, locale_t loc, const char *restrict fmt, ...)
79*c9945492SAndroid Build Coastguard Worker {
80*c9945492SAndroid Build Coastguard Worker 	va_list ap;
81*c9945492SAndroid Build Coastguard Worker 	ssize_t ret;
82*c9945492SAndroid Build Coastguard Worker 
83*c9945492SAndroid Build Coastguard Worker 	va_start(ap, fmt);
84*c9945492SAndroid Build Coastguard Worker 	ret = vstrfmon_l(s, n, loc, fmt, ap);
85*c9945492SAndroid Build Coastguard Worker 	va_end(ap);
86*c9945492SAndroid Build Coastguard Worker 
87*c9945492SAndroid Build Coastguard Worker 	return ret;
88*c9945492SAndroid Build Coastguard Worker }
89*c9945492SAndroid Build Coastguard Worker 
90*c9945492SAndroid Build Coastguard Worker 
strfmon(char * restrict s,size_t n,const char * restrict fmt,...)91*c9945492SAndroid Build Coastguard Worker ssize_t strfmon(char *restrict s, size_t n, const char *restrict fmt, ...)
92*c9945492SAndroid Build Coastguard Worker {
93*c9945492SAndroid Build Coastguard Worker 	va_list ap;
94*c9945492SAndroid Build Coastguard Worker 	ssize_t ret;
95*c9945492SAndroid Build Coastguard Worker 
96*c9945492SAndroid Build Coastguard Worker 	va_start(ap, fmt);
97*c9945492SAndroid Build Coastguard Worker 	ret = vstrfmon_l(s, n, CURRENT_LOCALE, fmt, ap);
98*c9945492SAndroid Build Coastguard Worker 	va_end(ap);
99*c9945492SAndroid Build Coastguard Worker 
100*c9945492SAndroid Build Coastguard Worker 	return ret;
101*c9945492SAndroid Build Coastguard Worker }
102