@@ -16,6 +16,53 @@ static int mp_octmod = 0;
1616static int mp_binmod = 0 ;
1717static int mp_basmod = 0 ;
1818
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+
1966#include <printf.h>
2067static int s_mp_print_mp_int (FILE * stream , const struct printf_info * info , const void * const * args )
2168{
@@ -29,13 +76,13 @@ static int s_mp_print_mp_int(FILE *stream, const struct printf_info *info, con
2976 /* Fiddle our bigint out of the argument list */
3077 a = * ((const mp_int * const * )(args [0 ]));
3178
32- if (( info -> user & mp_hexmod ) == 1 ) {
79+ if (info -> user & mp_hexmod ) {
3380 base = 16 ;
34- } else if (( info -> user & mp_binmod ) == 1 ) {
81+ } else if (info -> user & mp_binmod ) {
3582 base = 2 ;
36- } else if (( info -> user & mp_octmod ) == 1 ) {
83+ } else if (info -> user & mp_octmod ) {
3784 base = 8 ;
38- } else if (( info -> user & mp_basmod ) == 1 ) {
85+ } else if (info -> user & mp_basmod ) {
3986 base = 64 ;
4087 } else {
4188 base = 10 ;
@@ -129,6 +176,128 @@ static int s_mp_print_mp_int(FILE *stream, const struct printf_info *info, con
129176 return len ;
130177}
131178
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+
132301static int s_mp_print_mp_int_arginfo (const struct printf_info * info , size_t n ,
133302 int * argtypes , int * size )
134303{
@@ -141,6 +310,22 @@ static int s_mp_print_mp_int_arginfo(const struct printf_info *info, size_t n,
141310 return 1 ;
142311}
143312
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+
144329/* Fixed value: 'N' */
145330mp_err mp_printf_extension (void )
146331{
@@ -150,6 +335,10 @@ mp_err mp_printf_extension(void)
150335 /* Out of spec, which cannot happen if spec is fixed as we do it here. */
151336 err = MP_VAL ;
152337 }
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+ }
153342
154343 mp_hexmod = register_printf_modifier (L"k" );
155344 if (mp_hexmod < 0 ) {
0 commit comments