This source file includes following definitions.
- fmon_parse
- rpl_strfmon_l
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 #include <config.h>
18
19
20 #include <monetary.h>
21
22 #include <errno.h>
23 #include <locale.h>
24 #include <stdarg.h>
25 #include <stdbool.h>
26 #include <stdlib.h>
27 #include <string.h>
28
29 #undef strfmon_l
30
31
32 #define MAX_ARGS 16
33
34
35 typedef struct
36 {
37 bool needs_long_double;
38 const char *conversion_ptr;
39 }
40 directive_t;
41
42
43 typedef struct
44 {
45 size_t count;
46 directive_t dir[MAX_ARGS];
47 }
48 directives_t;
49
50
51
52
53 static int
54 fmon_parse (const char *format, directives_t *directivesp)
55 {
56 size_t count = 0;
57 const char *cp = format;
58
59 while (*cp != '\0')
60 {
61 if (*cp++ == '%')
62 {
63
64 while (*cp == '=' || *cp == '^' || *cp == '+' || *cp == '('
65 || *cp == '!' || *cp == '-')
66 {
67 if (*cp == '=')
68 {
69 cp++;
70 if (*cp == '\0')
71 return -1;
72 }
73 cp++;
74 }
75
76 while (*cp >= '0' && *cp <= '9')
77 cp++;
78
79 if (*cp == '#')
80 {
81 cp++;
82 while (*cp >= '0' && *cp <= '9')
83 cp++;
84 }
85
86 if (*cp == '.')
87 {
88 cp++;
89 while (*cp >= '0' && *cp <= '9')
90 cp++;
91 }
92
93 if (*cp != '%')
94 {
95 if (count == MAX_ARGS)
96
97 return -1;
98
99
100 if (*cp == 'L')
101 {
102 cp++;
103 directivesp->dir[count].needs_long_double = true;
104 }
105 else
106 directivesp->dir[count].needs_long_double = false;
107 if (!(*cp == 'i' || *cp == 'n'))
108 return -1;
109 directivesp->dir[count].conversion_ptr = cp;
110 count++;
111 }
112 cp++;
113 }
114 }
115
116 directivesp->count = count;
117 return 0;
118 }
119
120 ssize_t
121 rpl_strfmon_l (char *s, size_t maxsize, locale_t locale, const char *format, ...)
122 {
123
124
125 va_list argptr;
126 locale_t orig_locale;
127 directives_t directives;
128 ssize_t result;
129
130 orig_locale = uselocale ((locale_t)0);
131
132 if (uselocale (locale) == (locale_t)0)
133
134 return -1;
135
136
137
138
139
140
141
142 if (fmon_parse (format, &directives) < 0)
143 {
144 errno = EINVAL;
145 result = -1;
146 }
147 else
148 {
149 bool use_long_double;
150 unsigned int i;
151
152 use_long_double = false;
153 for (i = 0; i < directives.count; i++)
154 if (directives.dir[i].needs_long_double)
155 {
156 use_long_double = true;
157 break;
158 }
159
160 va_start (argptr, format);
161
162 if (use_long_double)
163 {
164 char *ld_format;
165
166
167 ld_format = (char *) malloc (strlen (format) + directives.count + 1);
168 if (ld_format == NULL)
169 {
170 errno = ENOMEM;
171 result = -1;
172 }
173 else
174 {
175 long double args[MAX_ARGS];
176
177
178 {
179 const char *p = format;
180 char *dest = ld_format;
181 for (i = 0; i < directives.count; i++)
182 {
183 const char *q = directives.dir[i].conversion_ptr;
184 memcpy (dest, p, q - p);
185 dest += q - p;
186 if (!directives.dir[i].needs_long_double)
187 *dest++ = 'L';
188 p = q;
189 }
190 strcpy (dest, p);
191 }
192
193
194 for (i = 0; i < directives.count; i++)
195 args[i] = (directives.dir[i].needs_long_double
196 ? va_arg (argptr, long double)
197 : (long double) va_arg (argptr, double));
198
199 for (; i < MAX_ARGS; i++)
200 args[i] = 0.0L;
201
202 result = strfmon_l (s, maxsize, locale, ld_format,
203 args[0], args[1], args[2], args[3], args[4],
204 args[5], args[6], args[7], args[8], args[9],
205 args[10], args[11], args[12], args[13],
206 args[14], args[15]);
207
208 free (ld_format);
209 }
210 }
211 else
212 {
213 double args[MAX_ARGS];
214
215
216 for (i = 0; i < directives.count; i++)
217 args[i] = va_arg (argptr, double);
218
219 for (; i < MAX_ARGS; i++)
220 args[i] = 0.0;
221
222 result = strfmon_l (s, maxsize, locale, format,
223 args[0], args[1], args[2], args[3], args[4],
224 args[5], args[6], args[7], args[8], args[9],
225 args[10], args[11], args[12], args[13], args[14],
226 args[15]);
227 }
228
229 va_end (argptr);
230 }
231
232 if (uselocale (orig_locale) == (locale_t)0)
233
234 return -1;
235
236 return result;
237 }