1 | #include <stdio.h> |
2 | #include <ctype.h> |
3 | #include <stdarg.h> |
4 | #include <monetary.h> |
5 | #include <errno(*__errno_location()).h> |
6 | #include "locale_impl.h" |
7 | |
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; |
| Value stored to 'fill' is never read |
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)(0 ? isdigit(*fmt) : ((unsigned)(*fmt)-'0') < 10); fmt++) |
53 | fw = 10*fw + (*fmt-'0'); |
54 | lp = 0; |
55 | rp = 2; |
56 | if (*fmt=='#') for (lp=0, fmt++; isdigit(*fmt)(0 ? isdigit(*fmt) : ((unsigned)(*fmt)-'0') < 10); fmt++) |
57 | lp = 10*lp + (*fmt-'0'); |
58 | if (*fmt=='.') for (rp=0, fmt++; isdigit(*fmt)(0 ? isdigit(*fmt) : ((unsigned)(*fmt)-'0') < 10); 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)__builtin_va_arg(ap,double); |
67 | l = snprintf(s, n, "%*.*f", w, rp, x); |
68 | if (l >= n) { |
69 | errno(*__errno_location()) = E2BIG7; |
70 | return -1; |
71 | } |
72 | s += l; |
73 | n -= l; |
74 | } |
75 | return s-s0; |
76 | } |
77 | |
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)__builtin_va_start(ap,fmt); |
84 | ret = vstrfmon_l(s, n, loc, fmt, ap); |
85 | va_end(ap)__builtin_va_end(ap); |
86 | |
87 | return ret; |
88 | } |
89 | |
90 | |
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)__builtin_va_start(ap,fmt); |
97 | ret = vstrfmon_l(s, n, CURRENT_LOCALE(__pthread_self()->locale), fmt, ap); |
98 | va_end(ap)__builtin_va_end(ap); |
99 | |
100 | return ret; |
101 | } |