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