@@ -16,6 +16,53 @@ static int mp_octmod = 0;
16
16
static int mp_binmod = 0 ;
17
17
static int mp_basmod = 0 ;
18
18
19
+ static void s_mp_str_reverse (char * s , int len )
20
+ {
21
+ int x = 0 , y = len - 1 ;
22
+ char t ;
23
+
24
+ while (x < y ) {
25
+ t = s [x ];
26
+ s [x ] = s [y ];
27
+ s [y ] = t ;
28
+ x ++ ;
29
+ y -- ;
30
+ }
31
+ }
32
+ static const char s_mp_base64 [] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/" ;
33
+ /* TODO: formatting. Precision and thousands separators (latter needs locale environment, so prob. not) */
34
+ static int s_mp_print_mp_digit_binary (mp_digit number , mp_digit base , bool prefix , char * buffer )
35
+ {
36
+ mp_digit cp , digit ;
37
+ int i = 0 ;
38
+
39
+ cp = number ;
40
+ while (cp != 0 ) {
41
+ digit = cp % base ;
42
+ cp /= base ;
43
+ buffer [i ++ ] = s_mp_base64 [digit ];
44
+ }
45
+ if (prefix && (base != 10 )) {
46
+ switch (base ) {
47
+ case 2 :
48
+ buffer [i ++ ] = 'b' ;
49
+ break ;
50
+ case 8 :
51
+ buffer [i ++ ] = 'o' ;
52
+ break ;
53
+ case 16 :
54
+ buffer [i ++ ] = 'x' ;
55
+ break ;
56
+ case 64 :
57
+ buffer [i ++ ] = '@' ;
58
+ break ;
59
+ }
60
+ buffer [i ++ ] = '0' ;
61
+ }
62
+ s_mp_str_reverse (buffer , i );
63
+ return i ;
64
+ }
65
+
19
66
#include <printf.h>
20
67
static int s_mp_print_mp_int (FILE * stream , const struct printf_info * info , const void * const * args )
21
68
{
@@ -29,13 +76,13 @@ static int s_mp_print_mp_int(FILE *stream, const struct printf_info *info, con
29
76
/* Fiddle our bigint out of the argument list */
30
77
a = * ((const mp_int * const * )(args [0 ]));
31
78
32
- if (( info -> user & mp_hexmod ) == 1 ) {
79
+ if (info -> user & mp_hexmod ) {
33
80
base = 16 ;
34
- } else if (( info -> user & mp_binmod ) == 1 ) {
81
+ } else if (info -> user & mp_binmod ) {
35
82
base = 2 ;
36
- } else if (( info -> user & mp_octmod ) == 1 ) {
83
+ } else if (info -> user & mp_octmod ) {
37
84
base = 8 ;
38
- } else if (( info -> user & mp_basmod ) == 1 ) {
85
+ } else if (info -> user & mp_basmod ) {
39
86
base = 64 ;
40
87
} else {
41
88
base = 10 ;
@@ -129,6 +176,128 @@ static int s_mp_print_mp_int(FILE *stream, const struct printf_info *info, con
129
176
return len ;
130
177
}
131
178
179
+ #include <inttypes.h>
180
+ #define LTM_FORMAT_BUFSIZ 127
181
+ static int s_mp_print_mp_digit (FILE * stream , const struct printf_info * info , const void * const * args )
182
+ {
183
+ mp_digit a ;
184
+ int len = 0 , base = 10 , l = 0 ;
185
+ char format [LTM_FORMAT_BUFSIZ ] = {0 };
186
+ char * format_p ;
187
+ char buf [LTM_FORMAT_BUFSIZ ] = {0 };
188
+
189
+ a = * ((mp_digit const * )(args [0 ]));
190
+
191
+ format_p = format ;
192
+
193
+ * format_p ++ = '%' ;
194
+ len ++ ;
195
+ if (info -> alt ) {
196
+ * format_p ++ = '#' ;
197
+ len ++ ;
198
+ }
199
+ /* Not with an "u" specifier
200
+ if(info->space){
201
+ *format_p++ = ' ';
202
+ len++;
203
+ }
204
+ */
205
+ if (info -> group ) {
206
+ * format_p ++ = '\'' ;
207
+ len ++ ;
208
+ }
209
+ /* Not with an "u" specifier
210
+ if(info->showsign){
211
+ *format_p++ = '+';
212
+ len++;
213
+ }
214
+ */
215
+ if (info -> width > 0 ) {
216
+ /* ceil(log10(2^64)) + 1 */
217
+ if ((len + 21 ) >= LTM_FORMAT_BUFSIZ ) {
218
+ return -1 ;
219
+ }
220
+ /* TODO: such a large cannon for such a tiny sparrow? */
221
+ l = sprintf (format_p , "%d" , info -> left ? - info -> width : info -> width );
222
+ format_p += l ;
223
+ len += l ;
224
+ }
225
+
226
+ if (info -> prec > 0 ) {
227
+ if ((len + 21 ) >= LTM_FORMAT_BUFSIZ ) {
228
+ return -1 ;
229
+ }
230
+ * format_p ++ = '.' ;
231
+ l = sprintf (format_p , "%d" , info -> prec );
232
+ format_p += l ;
233
+
234
+ }
235
+ /* strlen("llu") + 1 */
236
+ if ((len + 4 ) >= LTM_FORMAT_BUFSIZ ) {
237
+ return -1 ;
238
+ }
239
+ /* TODO: Single difference is PRT_64 to PRT_32 */
240
+ #ifdef MP_64BIT
241
+ if (info -> user & mp_hexmod ) {
242
+ len += sprintf (format_p , "%s" , "" PRIx64 "" );
243
+ } else if ((info -> user & mp_binmod )) {
244
+ if ((len + 66 ) >= LTM_FORMAT_BUFSIZ ) {
245
+ return -1 ;
246
+ }
247
+ (void )s_mp_print_mp_digit_binary (a , 2 , info -> alt , buf );
248
+ * format_p ++ = 's' ;
249
+ len ++ ;
250
+ base = 2 ;
251
+ } else if (info -> user & mp_octmod ) {
252
+ len += sprintf (format_p , "%s" , "" PRIo64 "" );
253
+ } else if (info -> user & mp_basmod ) {
254
+ if ((len + 12 ) >= LTM_FORMAT_BUFSIZ ) {
255
+ return -1 ;
256
+ }
257
+ (void )s_mp_print_mp_digit_binary (a , 64 , info -> alt , buf );
258
+ * format_p ++ = 's' ;
259
+ len ++ ;
260
+ base = 64 ;
261
+ } else {
262
+ len += sprintf (format_p , "%s" , "" PRIu64 "" );
263
+ }
264
+ #else
265
+ if (info -> user & mp_hexmod ) {
266
+ len += sprintf (format_p , "%s" , "" PRIx32 "" );
267
+ } else if (info -> user & mp_binmod ) {
268
+ if ((len + 34 ) >= LTM_FORMAT_BUFSIZ ) {
269
+ return -1 ;
270
+ }
271
+ (void )s_mp_print_mp_digit_binary (a , 2 , info -> alt , buf );
272
+ * format_p ++ = 's' ;
273
+ len ++ ;
274
+ base = 2 ;
275
+ } else if (info -> user & mp_octmod ) {
276
+ len += sprintf (format_p , "%s" , "" PRIo32 "" );
277
+ } else if (info -> user & mp_basmod ) {
278
+ if ((len + 7 ) >= LTM_FORMAT_BUFSIZ ) {
279
+ return -1 ;
280
+ }
281
+ (void )s_mp_print_mp_digit_binary (a , 64 , info -> alt , buf );
282
+ * format_p ++ = 's' ;
283
+ len ++ ;
284
+ base = 64 ;
285
+ } else {
286
+ len += sprintf (format_p , "%s" , "" PRIu32 "" );
287
+ }
288
+ /* Unlikely. */
289
+ if (len >= LTM_FORMAT_BUFSIZ ) {
290
+ return -1 ;
291
+ }
292
+ #endif
293
+ if ((base == 2 ) || (base == 64 )) {
294
+ len = fprintf (stream , format , buf );
295
+ } else {
296
+ len = fprintf (stream , format , a );
297
+ }
298
+ return len ;
299
+ }
300
+
132
301
static int s_mp_print_mp_int_arginfo (const struct printf_info * info , size_t n ,
133
302
int * argtypes , int * size )
134
303
{
@@ -141,6 +310,22 @@ static int s_mp_print_mp_int_arginfo(const struct printf_info *info, size_t n,
141
310
return 1 ;
142
311
}
143
312
313
+ static int s_mp_print_mp_digit_arginfo (const struct printf_info * info , size_t n ,
314
+ int * argtypes , int * size )
315
+ {
316
+ (void )(info );
317
+
318
+ if (n > 0 ) {
319
+ #ifdef MP_16BIT
320
+ argtypes [0 ] = PA_INT | PA_FLAG_LONG_LONG ;
321
+ #else
322
+ argtypes [0 ] = PA_INT | PA_FLAG_LONG ;
323
+ #endif
324
+ size [0 ] = sizeof (mp_digit );
325
+ }
326
+ return 1 ;
327
+ }
328
+
144
329
/* Fixed value: 'N' */
145
330
mp_err mp_printf_extension (void )
146
331
{
@@ -150,6 +335,10 @@ mp_err mp_printf_extension(void)
150
335
/* Out of spec, which cannot happen if spec is fixed as we do it here. */
151
336
err = MP_VAL ;
152
337
}
338
+ /* We don't need two different functions. The specifier is in printf_info.spec (a wchar_t) */
339
+ if (register_printf_specifier ('M' , s_mp_print_mp_digit , s_mp_print_mp_digit_arginfo )< 0 ) {
340
+ err = MP_VAL ;
341
+ }
153
342
154
343
mp_hexmod = register_printf_modifier (L"k" );
155
344
if (mp_hexmod < 0 ) {
0 commit comments