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