Fix rc script order.
[dragonfly.git] / contrib / mpfr / vasprintf.c
1 /* mpfr_vasprintf -- main function for the printf functions family
2    plus helper macros & functions.
3
4 Copyright 2007, 2008, 2009 Free Software Foundation, Inc.
5 Contributed by the Arenaire and Cacao projects, INRIA.
6
7 This file is part of the GNU MPFR Library.
8
9 The GNU MPFR Library is free software; you can redistribute it and/or modify
10 it under the terms of the GNU Lesser General Public License as published by
11 the Free Software Foundation; either version 2.1 of the License, or (at your
12 option) any later version.
13
14 The GNU MPFR Library is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
17 License for more details.
18
19 You should have received a copy of the GNU Lesser General Public License
20 along with the GNU MPFR Library; see the file COPYING.LIB.  If not, write to
21 the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
22 MA 02110-1301, USA. */
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 /* The mpfr_printf-like functions are defined only if stdarg.h exists */
29 #ifdef HAVE_STDARG
30
31 #include <stdarg.h>
32
33 #ifndef HAVE_VA_COPY
34 # ifdef HAVE___VA_COPY
35 #  define va_copy(dst,src) __va_copy(dst, src)
36 # else
37 /* autoconf manual advocates this fallback.
38    This is also the solution chosen by gmp */
39 #  define va_copy(dst,src) \
40   do { memcpy(&(dst), &(src), sizeof(va_list)); } while (0)
41 # endif /* HAVE___VA_COPY */
42 #endif /* HAVE_VA_COPY */
43
44 #ifdef HAVE_WCHAR_H
45 #include <wchar.h>
46 #endif
47
48 #if defined (__cplusplus)
49 #include <cstddef>
50 #define __STDC_LIMIT_MACROS   /* SIZE_MAX defined with stdint.h inclusion */
51 #else
52 #include <stddef.h>             /* for ptrdiff_t */
53 #endif
54
55 #if HAVE_INTTYPES_H
56 # include <inttypes.h> /* for intmax_t */
57 #else
58 # if HAVE_STDINT_H
59 #  include <stdint.h> /* for WINT_MAX in particular */
60 # endif
61 #endif
62
63 #define MPFR_NEED_LONGLONG_H
64 #include "mpfr-impl.h"
65
66 /* Define a length modifier corresponding to mp_prec_t.
67    We use literal string instead of literal character so as to permit future
68    extension to long long int ("ll"). */
69 #if   _MPFR_PREC_FORMAT == 1
70 #define MPFR_PREC_FORMAT_TYPE "h"
71 #define MPFR_PREC_FORMAT_SIZE 1
72 #elif _MPFR_PREC_FORMAT == 2
73 #define MPFR_PREC_FORMAT_TYPE ""
74 #define MPFR_PREC_FORMAT_SIZE 0
75 #elif _MPFR_PREC_FORMAT == 3
76 #define MPFR_PREC_FORMAT_TYPE "l"
77 #define MPFR_PREC_FORMAT_SIZE 1
78 #else
79 #error "mpfr_prec_t size not supported"
80 #endif
81
82 #if (__GMP_MP_SIZE_T_INT == 1)
83 #define MPFR_EXP_FORMAT_SPEC "i"
84 #elif (__GMP_MP_SIZE_T_INT == 0)
85 #define MPFR_EXP_FORMAT_SPEC "li"
86 #else
87 #error "mp_exp_t size not supported"
88 #endif
89
90 /* Output for special values defined in the C99 standard */
91 #define MPFR_NAN_STRING_LC "nan"
92 #define MPFR_NAN_STRING_UC "NAN"
93 #define MPFR_NAN_STRING_LENGTH 3
94 #define MPFR_INF_STRING_LC "inf"
95 #define MPFR_INF_STRING_UC "INF"
96 #define MPFR_INF_STRING_LENGTH 3
97
98 /* The implicit \0 is useless, but we do not write num_to_text[16]
99    otherwise g++ complains. */
100 static const char num_to_text[] = "0123456789abcdef";
101
102 /* some macro and functions for parsing format string */
103
104 /* Read an integer; saturate to INT_MAX. */
105 #define READ_INT(ap, format, specinfo, field, label_out)                \
106   do {                                                                  \
107     while (*(format))                                                   \
108       {                                                                 \
109         int _i;                                                         \
110         switch (*(format))                                              \
111           {                                                             \
112           case '0':                                                     \
113           case '1':                                                     \
114           case '2':                                                     \
115           case '3':                                                     \
116           case '4':                                                     \
117           case '5':                                                     \
118           case '6':                                                     \
119           case '7':                                                     \
120           case '8':                                                     \
121           case '9':                                                     \
122             specinfo.field = (specinfo.field <= INT_MAX / 10) ?         \
123               specinfo.field * 10 : INT_MAX;                            \
124             _i = *(format) - '0';                                       \
125             MPFR_ASSERTN (_i >= 0 && _i <= 9);                          \
126             specinfo.field = (specinfo.field <= INT_MAX - _i) ?         \
127               specinfo.field + _i : INT_MAX;                            \
128             ++(format);                                                 \
129             break;                                                      \
130           case '*':                                                     \
131             specinfo.field = va_arg ((ap), int);                        \
132             ++(format);                                                 \
133           default:                                                      \
134             goto label_out;                                             \
135           }                                                             \
136       }                                                                 \
137   } while (0)
138
139 /* arg_t contains all the types described by the 'type' field of the
140    format string */
141 enum arg_t
142   {
143     NONE,
144     CHAR_ARG,
145     SHORT_ARG,
146     LONG_ARG,
147     LONG_LONG_ARG,
148     INTMAX_ARG,
149     SIZE_ARG,
150     PTRDIFF_ARG,
151     LONG_DOUBLE_ARG,
152     MPF_ARG,
153     MPQ_ARG,
154     MP_LIMB_ARG,
155     MP_LIMB_ARRAY_ARG,
156     MPZ_ARG,
157     MPFR_PREC_ARG,
158     MPFR_ARG,
159     UNSUPPORTED
160   };
161
162 /* Each conversion specification of the format string will be translated in a
163    printf_spec structure by the parser.
164    This structure is adapted from the GNU libc one. */
165 struct printf_spec
166 {
167   unsigned int alt:1;           /* # flag */
168   unsigned int space:1;         /* Space flag */
169   unsigned int left:1;          /* - flag */
170   unsigned int showsign:1;      /* + flag */
171   unsigned int group:1;         /* ' flag */
172
173   int width;                    /* Width */
174   int prec;                     /* Precision */
175
176   enum arg_t arg_type;          /* Type of argument */
177   mp_rnd_t rnd_mode;            /* Rounding mode */
178   char spec;                    /* Conversion specifier */
179
180   char pad;                     /* Padding character */
181 };
182
183 static void
184 specinfo_init (struct printf_spec *specinfo)
185 {
186   specinfo->alt = 0;
187   specinfo->space = 0;
188   specinfo->left = 0;
189   specinfo->showsign = 0;
190   specinfo->group = 0;
191   specinfo->width = 0;
192   specinfo->prec = 0;
193   specinfo->arg_type = NONE;
194   specinfo->rnd_mode = GMP_RNDN;
195   specinfo->spec = '\0';
196   specinfo->pad = ' ';
197 }
198
199 #define FLOATING_POINT_ARG_TYPE(at) \
200   ((at) == MPFR_ARG || (at) == MPF_ARG || (at) == LONG_DOUBLE_ARG)
201
202 #define INTEGER_LIKE_ARG_TYPE(at)                                       \
203   ((at) == SHORT_ARG || (at) == LONG_ARG || (at) == LONG_LONG_ARG       \
204    || (at) == INTMAX_ARG  || (at) == MPFR_PREC_ARG || (at) == MPZ_ARG   \
205    || (at) == MPQ_ARG || (at) == MP_LIMB_ARG || (at) == MP_LIMB_ARRAY_ARG \
206    || (at) == CHAR_ARG || (at) == SIZE_ARG || (at) == PTRDIFF_ARG)
207
208 static int
209 specinfo_is_valid (struct printf_spec spec)
210 {
211   switch (spec.spec)
212     {
213     case 'n':
214       return -1;
215
216     case 'a':    case 'A':
217     case 'e':    case 'E':
218     case 'f':    case 'F':
219     case 'g':    case 'G':
220       return (spec.arg_type == NONE
221               || FLOATING_POINT_ARG_TYPE (spec.arg_type));
222
223     case 'b':
224       return spec.arg_type == MPFR_ARG;
225
226     case 'd':    case 'i':
227     case 'u':    case 'o':
228     case 'x':    case 'X':
229       return (spec.arg_type == NONE
230               || INTEGER_LIKE_ARG_TYPE (spec.arg_type));
231
232     case 'c':
233     case 's':
234       return (spec.arg_type == NONE || spec.arg_type == LONG_ARG);
235
236     case 'p':
237       return spec.arg_type == NONE;
238
239     default:
240       return 0;
241     }
242 }
243
244 static const char *
245 parse_flags (const char *format, struct printf_spec *specinfo)
246 {
247   while (*format)
248     {
249       switch (*format)
250         {
251         case '0':
252           specinfo->pad = '0';
253           ++format;
254           break;
255         case '#':
256           specinfo->alt = 1;
257           ++format;
258           break;
259         case '+':
260           specinfo->showsign = 1;
261           ++format;
262           break;
263         case ' ':
264           specinfo->space = 1;
265           ++format;
266           break;
267         case '-':
268           specinfo->left = 1;
269           ++format;
270           break;
271         case '\'':
272           /* Single UNIX Specification for thousand separator */
273           specinfo->group = 1;
274           ++format;
275           break;
276         default:
277           return format;
278         }
279     }
280   return format;
281 }
282
283 static const char *
284 parse_arg_type (const char *format, struct printf_spec *specinfo)
285 {
286   switch (*format)
287     {
288     case '\0':
289       break;
290     case 'h':
291       if (*++format == 'h')
292 #ifndef NPRINTF_HH
293         {
294           ++format;
295           specinfo->arg_type = CHAR_ARG;
296         }
297 #else
298         specinfo->arg_type = UNSUPPORTED;
299 #endif
300       else
301         specinfo->arg_type = SHORT_ARG;
302       break;
303     case 'l':
304       if (*++format == 'l')
305         {
306           ++format;
307 #if defined (HAVE_LONG_LONG) && !defined(NPRINTF_LL)
308           specinfo->arg_type = LONG_LONG_ARG;
309 #else
310           specinfo->arg_type = UNSUPPORTED;
311 #endif
312           break;
313         }
314       else
315         {
316           specinfo->arg_type = LONG_ARG;
317           break;
318         }
319     case 'j':
320       ++format;
321 #if defined(_MPFR_H_HAVE_INTMAX_T) && !defined(NPRINTF_J)
322       specinfo->arg_type = INTMAX_ARG;
323 #else
324       specinfo->arg_type = UNSUPPORTED;
325 #endif
326       break;
327     case 'z':
328       ++format;
329       specinfo->arg_type = SIZE_ARG;
330       break;
331     case 't':
332       ++format;
333 #ifndef NPRINTF_T
334       specinfo->arg_type = PTRDIFF_ARG;
335 #else
336       specinfo->arg_type = UNSUPPORTED;
337 #endif
338       break;
339     case 'L':
340       ++format;
341 #ifndef NPRINTF_L
342       specinfo->arg_type = LONG_DOUBLE_ARG;
343 #else
344       specinfo->arg_type = UNSUPPORTED;
345 #endif
346       break;
347     case 'F':
348       ++format;
349       specinfo->arg_type = MPF_ARG;
350       break;
351     case 'Q':
352       ++format;
353       specinfo->arg_type = MPQ_ARG;
354       break;
355     case 'M':
356       ++format;
357       /* The 'M' specifier was added in gmp 4.2.0 */
358       specinfo->arg_type = MP_LIMB_ARG;
359       break;
360     case 'N':
361       ++format;
362       specinfo->arg_type = MP_LIMB_ARRAY_ARG;
363       break;
364     case 'Z':
365       ++format;
366       specinfo->arg_type = MPZ_ARG;
367       break;
368
369       /* mpfr specific specifiers */
370     case 'P':
371       ++format;
372       specinfo->arg_type = MPFR_PREC_ARG;
373       break;
374     case 'R':
375       ++format;
376       specinfo->arg_type = MPFR_ARG;
377     }
378   return format;
379 }
380
381
382 /* some macros and functions filling the buffer */
383
384 /* CONSUME_VA_ARG removes from va_list AP the type expected by SPECINFO */
385
386 /* With a C++ compiler wchar_t and enumeration in va_list are converted to
387    integer type : int, unsigned int, long or unsigned long (unfortunately,
388    this is implementation dependant).
389    We follow gmp which assumes in print/doprnt.c that wchar_t is converted
390    to int (because wchar_t <= int).
391    For wint_t, we assume that the case WINT_MAX < INT_MAX yields an
392    integer promotion. */
393 #ifdef HAVE_WCHAR_H
394 #if defined(WINT_MAX) && WINT_MAX < INT_MAX
395 typedef int    mpfr_va_wint;  /* integer promotion */
396 #else
397 typedef wint_t mpfr_va_wint;
398 #endif
399 #define CASE_LONG_ARG(specinfo, ap)                                     \
400   case LONG_ARG:                                                        \
401   if (((specinfo).spec == 'd') || ((specinfo).spec == 'i')              \
402       || ((specinfo).spec == 'o') || ((specinfo).spec == 'u')           \
403       || ((specinfo).spec == 'x') || ((specinfo).spec == 'X'))          \
404     (void) va_arg ((ap), long);                                         \
405   else if ((specinfo).spec == 'c')                                      \
406     (void) va_arg ((ap), mpfr_va_wint);                                 \
407   else if ((specinfo).spec == 's')                                      \
408     (void) va_arg ((ap), int); /* we assume integer promotion */        \
409   break;
410 #else
411 #define CASE_LONG_ARG(specinfo, ap)             \
412   case LONG_ARG:                                \
413   (void) va_arg ((ap), long);                   \
414   break;
415 #endif
416
417 #if defined(_MPFR_H_HAVE_INTMAX_T)
418 #define CASE_INTMAX_ARG(specinfo, ap)           \
419   case INTMAX_ARG:                              \
420   (void) va_arg ((ap), intmax_t);               \
421   break;
422 #else
423 #define CASE_INTMAX_ARG(specinfo, ap)
424 #endif
425
426 #ifdef HAVE_LONG_LONG
427 #define CASE_LONG_LONG_ARG(specinfo, ap)        \
428   case LONG_LONG_ARG:                           \
429   (void) va_arg ((ap), long long);              \
430   break;
431 #else
432 #define CASE_LONG_LONG_ARG(specinfo, ap)
433 #endif
434
435 #define CONSUME_VA_ARG(specinfo, ap)            \
436   do {                                          \
437     switch ((specinfo).arg_type)                \
438       {                                         \
439       case CHAR_ARG:                            \
440       case SHORT_ARG:                           \
441         (void) va_arg ((ap), int);              \
442         break;                                  \
443       CASE_LONG_ARG (specinfo, ap)              \
444       CASE_LONG_LONG_ARG (specinfo, ap)         \
445       CASE_INTMAX_ARG (specinfo, ap)            \
446       case SIZE_ARG:                            \
447         (void) va_arg ((ap), size_t);           \
448         break;                                  \
449       case PTRDIFF_ARG:                         \
450         (void) va_arg ((ap), ptrdiff_t);        \
451         break;                                  \
452       case LONG_DOUBLE_ARG:                     \
453         (void) va_arg ((ap), long double);      \
454         break;                                  \
455       case MPF_ARG:                             \
456         (void) va_arg ((ap), mpf_srcptr);       \
457         break;                                  \
458       case MPQ_ARG:                             \
459         (void) va_arg ((ap), mpq_srcptr);       \
460         break;                                  \
461       case MP_LIMB_ARG:                         \
462         (void) va_arg ((ap), mp_limb_t);        \
463         break;                                  \
464       case MP_LIMB_ARRAY_ARG:                   \
465         (void) va_arg ((ap), mp_ptr);           \
466         (void) va_arg ((ap), mp_size_t);        \
467         break;                                  \
468       case MPZ_ARG:                             \
469         (void) va_arg ((ap), mpz_srcptr);       \
470         break;                                  \
471       default:                                  \
472         switch ((specinfo).spec)                \
473           {                                     \
474           case 'd':                             \
475           case 'i':                             \
476           case 'o':                             \
477           case 'u':                             \
478           case 'x':                             \
479           case 'X':                             \
480           case 'c':                             \
481             (void) va_arg ((ap), int);          \
482             break;                              \
483           case 'f':                             \
484           case 'F':                             \
485           case 'e':                             \
486           case 'E':                             \
487           case 'g':                             \
488           case 'G':                             \
489           case 'a':                             \
490           case 'A':                             \
491             (void) va_arg ((ap), double);       \
492             break;                              \
493           case 's':                             \
494             (void) va_arg ((ap), char *);       \
495             break;                              \
496           case 'p':                             \
497             (void) va_arg ((ap), void *);       \
498           }                                     \
499       }                                         \
500   } while (0)
501
502 /* process the format part which does not deal with mpfr types,
503    jump to external label 'error' if gmp_asprintf return -1. */
504 #define FLUSH(flag, start, end, ap, buf_ptr)                            \
505   do {                                                                  \
506     const size_t n = (end) - (start);                                   \
507     if ((flag))                                                         \
508       /* previous specifiers are understood by gmp_printf */            \
509       {                                                                 \
510         MPFR_TMP_DECL (marker);                                         \
511         char *fmt_copy;                                                 \
512         MPFR_TMP_MARK (marker);                                         \
513         fmt_copy = (char*) MPFR_TMP_ALLOC ((n + 1) * sizeof(char));     \
514         strncpy (fmt_copy, (start), n);                                 \
515         fmt_copy[n] = '\0';                                             \
516         if (sprntf_gmp ((buf_ptr), (fmt_copy), (ap)) == -1)             \
517           {                                                             \
518             MPFR_TMP_FREE (marker);                                     \
519             goto error;                                                 \
520           }                                                             \
521         (flag) = 0;                                                     \
522         MPFR_TMP_FREE (marker);                                         \
523       }                                                                 \
524     else if ((start) != (end))                                          \
525       /* no conversion specification, just simple characters */         \
526       buffer_cat ((buf_ptr), (start), n);                               \
527   } while (0)
528
529 struct string_buffer
530 {
531   char *start;                  /* beginning of the buffer */
532   char *curr;                   /* null terminating character */
533   size_t size;                  /* buffer capacity */
534 };
535
536 static void
537 buffer_init (struct string_buffer *b, size_t s)
538 {
539   b->start = (char *) (*__gmp_allocate_func) (s);
540   b->start[0] = '\0';
541   b->curr = b->start;
542   b->size = s;
543 }
544
545 /* Increase buffer size by a number of character being the least multiple of
546    4096 greater than LEN+1. */
547 static void
548 buffer_widen (struct string_buffer *b, size_t len)
549 {
550   const size_t pos = b->curr - b->start;
551   const size_t n = sizeof (char) * (0x1000 + (len & ~((size_t) 0xfff)));
552   MPFR_ASSERTD (pos < b->size);
553
554   MPFR_ASSERTN ((len & ~((size_t) 4095)) <= SIZE_MAX / sizeof (char) - 4096);
555   MPFR_ASSERTN (b->size < SIZE_MAX - n);
556
557   b->start =
558     (char *) (*__gmp_reallocate_func) (b->start, b->size, b->size + n);
559   b->size += n;
560   b->curr = b->start + pos;
561
562   MPFR_ASSERTD (pos < b->size);
563   MPFR_ASSERTD (*b->curr == '\0');
564 }
565
566 /* Concatenate the LEN first characters of the string S to the buffer B and
567    expand it if needed. */
568 static void
569 buffer_cat (struct string_buffer *b, const char *s, size_t len)
570 {
571   MPFR_ASSERTD (len != 0);
572   MPFR_ASSERTD (len <= strlen (s));
573
574   if (MPFR_UNLIKELY ((b->curr + len) >= (b->start + b->size)))
575     buffer_widen (b, len);
576
577   strncat (b->curr, s, len);
578   b->curr += len;
579
580   MPFR_ASSERTD (b->curr < b->start + b->size);
581   MPFR_ASSERTD (*b->curr == '\0');
582 }
583
584 /* Add N characters C to the end of buffer B */
585 static void
586 buffer_pad (struct string_buffer *b, const char c, const size_t n)
587 {
588   MPFR_ASSERTD (n != 0);
589
590   MPFR_ASSERTN (b->size < SIZE_MAX - n - 1);
591   if (MPFR_UNLIKELY ((b->curr + n + 1) > (b->start + b->size)))
592     buffer_widen (b, n);
593
594   if (n == 1)
595     *b->curr = c;
596   else
597     memset (b->curr, c, n);
598   b->curr += n;
599   *b->curr = '\0';
600
601   MPFR_ASSERTD (b->curr < b->start + b->size);
602 }
603
604 /* Form a string by concatenating the first LEN characters of STR to TZ
605    zero(s), insert into one character C each 3 characters starting from end
606    to begining and concatenate the result to the buffer B. */
607 static void
608 buffer_sandwich (struct string_buffer *b, char *str, size_t len,
609                  const size_t tz, const char c)
610 {
611   const size_t step = 3;
612   const size_t size = len + tz;
613   const size_t r = size % step == 0 ? step : size % step;
614   const size_t q = size % step == 0 ? size / step - 1 : size / step;
615   size_t i;
616
617   MPFR_ASSERTD (size != 0);
618   if (c == '\0')
619     {
620       buffer_cat (b, str, len);
621       buffer_pad (b, '0', tz);
622       return;
623     }
624
625   MPFR_ASSERTN (b->size < SIZE_MAX - size - 1 - q);
626   MPFR_ASSERTD (len <= strlen (str));
627   if (MPFR_UNLIKELY ((b->curr + size + 1 + q) > (b->start + b->size)))
628     buffer_widen (b, size + q);
629
630   /* first R significant digits */
631   memcpy (b->curr, str, r);
632   b->curr += r;
633   str += r;
634   len -= r;
635
636   /* blocks of thousands. Warning: STR might end in the middle of a block */
637   for (i = 0; i < q; ++i)
638     {
639       *b->curr++ = c;
640       if (MPFR_LIKELY (len > 0))
641         {
642           if (MPFR_LIKELY (len >= step))
643             /* step significant digits */
644             {
645               memcpy (b->curr, str, step);
646               len -= step;
647             }
648           else
649             /* last digits in STR, fill up thousand block with zeros */
650             {
651               memcpy (b->curr, str, len);
652               memset (b->curr + len, '0', step - len);
653               len = 0;
654             }
655         }
656       else
657         /* trailing zeros */
658         memset (b->curr, '0', step);
659
660       b->curr += step;
661       str += step;
662     }
663
664   *b->curr = '\0';
665
666   MPFR_ASSERTD (b->curr < b->start + b->size);
667 }
668
669 /* let gmp_xprintf process the part it can understand */
670 static int
671 sprntf_gmp (struct string_buffer *b, const char *fmt, va_list ap)
672 {
673   int length;
674   char *s;
675
676   length = gmp_vasprintf (&s, fmt, ap);
677   if (length > 0)
678     buffer_cat (b, s, length);
679
680   mpfr_free_str (s);
681   return length;
682 }
683
684 /* Helper struct and functions for temporary strings management */
685 /* struct for easy string clearing */
686 struct string_list
687 {
688   char *string;
689   struct string_list *next; /* NULL in last node */
690 };
691
692 /* initialisation */
693 static void
694 init_string_list (struct string_list *sl)
695 {
696   sl->string = NULL;
697   sl->next = NULL;
698 }
699
700 /* clear all strings in the list */
701 static void
702 clear_string_list (struct string_list *sl)
703 {
704   struct string_list *n;
705
706   while (sl)
707     {
708       if (sl->string)
709         mpfr_free_str (sl->string);
710       n = sl->next;
711       (*__gmp_free_func) (sl, sizeof(struct string_list));
712       sl = n;
713     }
714 }
715
716 /* add a string in the list */
717 static char *
718 register_string (struct string_list *sl, char *new_string)
719 {
720   /* look for the last node */
721   while (sl->next)
722     sl = sl->next;
723
724   sl->next = (struct string_list*)
725     (*__gmp_allocate_func) (sizeof (struct string_list));
726
727   sl = sl->next;
728   sl->next = NULL;
729   return sl->string = new_string;
730 }
731
732 /* padding type: where are the padding characters */
733 enum pad_t
734   {
735     LEFT,          /* spaces in left hand side for right justification */
736     LEADING_ZEROS, /* padding with '0' characters in integral part */
737     RIGHT          /* spaces in right hand side for left justification */
738   };
739
740 /* number_parts details how much characters are needed in each part of a float
741    print.  */
742 struct number_parts
743 {
744   enum pad_t pad_type;    /* Padding type */
745   size_t pad_size;        /* Number of padding characters */
746
747   char sign;              /* Sign character */
748
749   char *prefix_ptr;       /* Pointer to prefix part */
750   size_t prefix_size;     /* Number of characters in *prefix_ptr */
751
752   char thousands_sep;     /* Thousands separator (only with style 'f') */
753
754   char *ip_ptr;           /* Pointer to integral part characters*/
755   size_t ip_size;         /* Number of digits in *ip_ptr */
756   int ip_trailing_zeros;  /* Number of additional null digits in integral
757                              part */
758
759   char point;             /* Decimal point character */
760
761   int fp_leading_zeros;   /* Number of additional leading zeros in fractional
762                              part */
763   char *fp_ptr;           /* Pointer to fractional part characters */
764   size_t fp_size;         /* Number of digits in *fp_ptr */
765   int fp_trailing_zeros;  /* Number of additional trailing zeros in fractional
766                              part */
767
768   char *exp_ptr;          /* Pointer to exponent part */
769   size_t exp_size;        /* Number of characters in *exp_ptr */
770
771   struct string_list *sl; /* List of string buffers in use: we need such a
772                              mechanism because fp_ptr may point into the same
773                              string as ip_ptr */
774 };
775
776 /* For a real non zero number x, what is the base exponent f when rounding x
777    with rounding mode r to r(x) = m*b^f, where m is a digit and 1 <= m < b ?
778    Return non zero value if x is rounded up to b^f, return zero otherwise */
779 static int
780 next_base_power_p (mpfr_srcptr x, int base, mpfr_rnd_t rnd)
781 {
782   mp_prec_t nbits;
783   mp_limb_t pm;
784   mp_limb_t xm;
785
786   MPFR_ASSERTD (MPFR_IS_PURE_FP (x));
787   MPFR_ASSERTD (base == 2 || base == 16);
788
789   /* Warning: the decimal point is AFTER THE FIRST DIGIT in this output
790      representation. */
791   nbits = base == 2 ? 1 : 4;
792
793   if (rnd == GMP_RNDZ
794       || (rnd == GMP_RNDD && MPFR_IS_POS (x))
795       || (rnd == GMP_RNDU && MPFR_IS_NEG (x))
796       || MPFR_PREC (x) <= nbits)
797     /* no rounding when printing x with 1 digit */
798     return 0;
799
800   xm = MPFR_MANT (x) [MPFR_LIMB_SIZE (x) - 1];
801   pm = MPFR_LIMB_MASK (BITS_PER_MP_LIMB - nbits);
802   if ((xm & ~pm) ^ ~pm)
803     /* do no round up if some of the nbits first bits are 0s. */
804     return 0;
805
806   if (rnd == GMP_RNDN)
807     /* mask for rounding bit */
808     pm = (MPFR_LIMB_ONE << (BITS_PER_MP_LIMB - nbits - 1));
809
810   /* round up if some remaining bits are 1 */
811   /* warning: the return value must be an int */
812   return xm & pm ? 1 : 0;
813 }
814
815 /* For a real non zero number x, what is the exponent f when rounding x with
816    rounding mode r to r(x) = m*10^f, where m has p+1 digits and 1 <= m < 10 ?
817
818    Return +1 if x is rounded up to 10^f, return zero otherwise.
819    If e is not NULL, *e is set to f. */
820 static int
821 round_to_10_power (mp_exp_t *e, mpfr_srcptr x, mp_prec_t p, mpfr_rnd_t r)
822 {
823   mpfr_t f, u, v, y;
824   mp_prec_t m;
825   mp_exp_t ex;
826   mpfr_uexp_t uexp;
827   int roundup = -1; /* boolean (-1: not set) */
828
829   MPFR_ZIV_DECL (loop);
830
831   /* y = abs(x) */
832   MPFR_ALIAS (y, x, 1, MPFR_EXP(x));
833
834   /* we want f = floor(log(|x|)/log(10)) exactly.
835      we have |f| >= |Exp(x)|/3,
836      then m = ceil(log(uexp/3)/log(2)) > log(f)/log(2)
837      is a sufficient precision for f. */
838   ex = mpfr_get_exp (x);
839   uexp = SAFE_ABS (mpfr_uexp_t, ex) / 3;
840   m = 1;
841   while (uexp)
842     {
843       uexp >>= 1;
844       m++;
845     }
846   if (m < 2)
847     m = 2;
848   mpfr_init2 (f, m);
849   mpfr_log10 (f, y, GMP_RNDD);
850   mpfr_floor (f, f);
851
852   /* In most cases, the output exponent is f. */
853   if (e != NULL)
854     *e = (mp_exp_t)mpfr_get_si (f, GMP_RNDD);
855
856   if (r == GMP_RNDZ
857       || (MPFR_IS_POS (x) && r == GMP_RNDD)
858       || (MPFR_IS_NEG (x) && r == GMP_RNDU))
859     /* If rounding toward zero, the exponent is f */
860     {
861       mpfr_clear (f);
862       return 0;
863     }
864
865   /* Is |x| less than 10^(f+1) - 10^(f-p)? */
866   {
867     int cmp;
868     int inex_u, inex_v, inex_w;
869     mp_exp_t exp_u, exp_v, exp_w;
870
871     m = MPFR_PREC (x);
872     m += MPFR_INT_CEIL_LOG2 (m);
873     mpfr_init2 (u, m);
874     mpfr_init2 (v, m);
875
876     MPFR_ZIV_INIT (loop, m);
877     for (;;)
878       {
879         mpfr_set_prec (u, m);
880         mpfr_set_prec (v, m);
881
882         /* u = o(10^(f+1)) rounding toward -infinity
883            error (u) < 1 ulp(u)
884            error(u) = 0 if inex_u = 0 */
885         mpfr_add_ui (u, f, 1, GMP_RNDN);
886         inex_u = mpfr_ui_pow (u, 10, u, GMP_RNDD);
887         exp_u = MPFR_EXP (u);
888
889         /* if r = rounding to nearest
890            v = o(0.5 * 10^(f-p)) rounding toward +infinity
891            else
892            v = o(10^(f-p)) rounding toward +infinity
893
894            error(v) < 1 ulp(v)
895            error(v) = 0 if inex_v = 0 */
896         mpfr_sub_ui (v, f, p, GMP_RNDN);
897         inex_v = mpfr_ui_pow (v, 10, v, GMP_RNDU);
898         if (r == GMP_RNDN)
899           mpfr_div_2ui (v, v, 1, GMP_RNDN);
900         exp_v = MPFR_EXP (v);
901
902         /* w = o(u-v) rounding toward -infinity
903            w is an approximation of 10^(f+1) - v with
904            error(w) < 1 ulp(w) + error(u) + error(v)
905            error(w) = 0 iff inex_u = inex_v = inex_diff = 0 */
906         inex_w = mpfr_sub (u, u, v, GMP_RNDD);
907         exp_w = MPFR_EXP (u);
908
909         cmp = mpfr_cmp (y, u);
910
911         if (cmp < 0)
912           /* |x| < u <= 10^(f+1) - v, the exponent is f */
913           {
914             roundup = 0;
915             break;
916           }
917         else if (cmp == 0 && inex_u == 0 && inex_v == 0 && inex_w == 0)
918           /* |x| = u = 10^(f+1) - v, the exponent is f+1 */
919           {
920             if (e != NULL)
921               (*e)++;
922
923             roundup = +1;
924             break;
925           }
926
927           /* compare |x| with w + error(w) */
928         if (inex_u)
929           mpfr_set_ui_2exp (v, 1, exp_u - m, GMP_RNDU);
930         else
931           mpfr_set_ui (v, 0, GMP_RNDN);
932         if (inex_v)
933           mpfr_set_ui_2exp (v, 1, exp_v - m, GMP_RNDU);
934         if (inex_w)
935           mpfr_set_ui_2exp (v, 1, exp_w - m, GMP_RNDU);
936
937         mpfr_add (u, u, v, GMP_RNDU);
938         if (mpfr_cmp (y, u) >= 0)
939           {
940             if (e != NULL)
941               *e = (mp_exp_t)mpfr_get_si (f, GMP_RNDD) + 1;
942
943             roundup = +1;
944             break;
945           }
946
947         MPFR_ZIV_NEXT (loop, m);
948       }
949     MPFR_ZIV_FREE (loop);
950     mpfr_clear (u);
951     mpfr_clear (v);
952   }
953
954   MPFR_ASSERTD (roundup != -1);
955   mpfr_clear (f);
956   return roundup;
957 }
958
959 /* Determine the different parts of the string representation of the regular
960    number P when SPEC.SPEC is 'a', 'A', or 'b'.
961
962    return -1 if some field > INT_MAX */
963 static int
964 regular_ab (struct number_parts *np, mpfr_srcptr p,
965             const struct printf_spec spec)
966 {
967   int uppercase;
968   int base;
969   char *str;
970   mp_exp_t exp;
971
972   uppercase = spec.spec == 'A';
973
974   /* sign */
975   if (MPFR_IS_NEG (p))
976     np->sign = '-';
977   else if (spec.showsign || spec.space)
978     np->sign = spec.showsign ? '+' : ' ';
979
980   if (spec.spec == 'a' || spec.spec == 'A')
981     /* prefix part */
982     {
983       np->prefix_size = 2;
984       str = (char *) (*__gmp_allocate_func) (1 + np->prefix_size);
985       str[0] = '0';
986       str[1] = uppercase ? 'X' : 'x';
987       str[2] = '\0';
988       np->prefix_ptr = register_string (np->sl, str);
989     }
990
991   /* integral part */
992   np->ip_size = 1;
993   base = (spec.spec == 'b') ? 2 : 16;
994
995   if (spec.prec != 0)
996     {
997       size_t nsd;
998
999       /* Number of significant digits:
1000          - if no given precision, let mpfr_get_str determine it;
1001          - if a non-zero precision is specified, then one digit before decimal
1002          point plus SPEC.PREC after it. */
1003       nsd = spec.prec < 0 ? 0 : spec.prec + np->ip_size;
1004       str = mpfr_get_str (0, &exp, base, nsd, p, spec.rnd_mode);
1005       register_string (np->sl, str);
1006       np->ip_ptr = MPFR_IS_NEG (p) ? ++str : str;  /* skip sign if any */
1007
1008       if (base == 16)
1009         /* EXP is the exponent for radix sixteen with decimal point BEFORE the
1010            first digit, we want the exponent for radix two and the decimal
1011            point AFTER the first digit. */
1012         {
1013           MPFR_ASSERTN (exp > MPFR_EMIN_MIN /4); /* possible overflow */
1014           exp = (exp - 1) * 4;
1015         }
1016       else
1017         /* EXP is the exponent for decimal point BEFORE the first digit, we
1018            want the exponent for decimal point AFTER the first digit. */
1019         {
1020           MPFR_ASSERTN (exp > MPFR_EMIN_MIN); /* possible overflow */
1021           --exp;
1022         }
1023     }
1024   else if (next_base_power_p (p, base, spec.rnd_mode))
1025     {
1026       str = (char *)(*__gmp_allocate_func) (2);
1027       str[0] = '1';
1028       str[1] = '\0';
1029       np->ip_ptr = register_string (np->sl, str);
1030
1031       exp = MPFR_GET_EXP (p);
1032     }
1033   else if (base == 2)
1034     {
1035       str = (char *)(*__gmp_allocate_func) (2);
1036       str[0] = '1';
1037       str[1] = '\0';
1038       np->ip_ptr = register_string (np->sl, str);
1039
1040       exp = MPFR_GET_EXP (p) - 1;
1041     }
1042   else
1043     {
1044       int digit;
1045       mp_limb_t msl = MPFR_MANT (p)[MPFR_LIMB_SIZE (p) - 1];
1046       int rnd_bit = BITS_PER_MP_LIMB - 5;
1047
1048       /* pick up the 4 first bits */
1049       digit = msl >> (rnd_bit+1);
1050       if ((spec.rnd_mode == GMP_RNDU && MPFR_IS_POS (p))
1051           || (spec.rnd_mode == GMP_RNDD && MPFR_IS_NEG (p))
1052           || (spec.rnd_mode == GMP_RNDN
1053               && (msl & (MPFR_LIMB_ONE << rnd_bit))))
1054         digit++;
1055       MPFR_ASSERTD ((0 <= digit) && (digit <= 15));
1056
1057       str = (char *)(*__gmp_allocate_func) (1 + np->ip_size);
1058       str[0] = num_to_text [digit];
1059       str[1] = '\0';
1060       np->ip_ptr = register_string (np->sl, str);
1061
1062       exp = MPFR_GET_EXP (p) - 4;
1063     }
1064
1065   if (uppercase)
1066     /* All digits in upper case */
1067     {
1068       char *s1 = str;
1069       while (*s1)
1070         {
1071           switch (*s1)
1072             {
1073             case 'a':
1074               *s1 = 'A';
1075               break;
1076             case 'b':
1077               *s1 = 'B';
1078               break;
1079             case 'c':
1080               *s1 = 'C';
1081               break;
1082             case 'd':
1083               *s1 = 'D';
1084               break;
1085             case 'e':
1086               *s1 = 'E';
1087               break;
1088             case 'f':
1089               *s1 = 'F';
1090               break;
1091             }
1092           s1++;
1093         }
1094     }
1095
1096   if (spec.spec == 'b' || spec.prec != 0)
1097     /* compute the number of digits in fractional part */
1098     {
1099       char *ptr;
1100       size_t str_len;
1101
1102       /* the sign has been skipped, skip also the first digit */
1103       ++str;
1104       str_len = strlen (str);
1105       ptr = str + str_len - 1; /* points to the end of str */
1106
1107       if (spec.prec < 0)
1108         /* remove trailing zeros, if any */
1109         {
1110           while ((*ptr == '0') && (str_len != 0))
1111             {
1112               --ptr;
1113               --str_len;
1114             }
1115         }
1116
1117       if (str_len > INT_MAX)
1118         /* too many digits in fractional part */
1119         return -1;
1120
1121       if (str_len != 0)
1122         /* there are some non-zero digits in fractional part */
1123         {
1124           np->fp_ptr = str;
1125           np->fp_size = str_len;
1126           if ((int) str_len < spec.prec)
1127             np->fp_trailing_zeros = spec.prec - str_len;
1128         }
1129     }
1130
1131   /* decimal point */
1132   if ((np->fp_size != 0) || spec.alt)
1133     np->point = MPFR_DECIMAL_POINT;
1134
1135   /* the exponent part contains the character 'p', or 'P' plus the sign
1136      character plus at least one digit and only as many more digits as
1137      necessary to represent the exponent.
1138      We assume that |EXP| < 10^INT_MAX. */
1139   np->exp_size = 3;
1140   {
1141     mp_exp_unsigned_t x;
1142
1143     x = SAFE_ABS (mp_exp_unsigned_t, exp);
1144     while (x > 9)
1145       {
1146         np->exp_size++;
1147         x /= 10;
1148       }
1149   }
1150   str = (char *) (*__gmp_allocate_func) (1 + np->exp_size);
1151   np->exp_ptr = register_string (np->sl, str);
1152   {
1153     char exp_fmt[8];  /* contains at most 7 characters like in "p%+.1i",
1154                          or "P%+.2li" */
1155
1156     exp_fmt[0] = uppercase ? 'P' : 'p';
1157     exp_fmt[1] = '\0';
1158     strcat (exp_fmt, "%+.1" MPFR_EXP_FORMAT_SPEC);
1159
1160     if (sprintf (str, exp_fmt, exp) < 0)
1161       return -1;
1162   }
1163
1164   return 0;
1165 }
1166
1167 /* Determine the different parts of the string representation of the regular
1168    number P when SPEC.SPEC is 'e', 'E', 'g', or 'G'.
1169
1170    return -1 if some field > INT_MAX */
1171 static int
1172 regular_eg (struct number_parts *np, mpfr_srcptr p,
1173             const struct printf_spec spec)
1174 {
1175   char *str;
1176   mp_exp_t exp;
1177
1178   const int uppercase = spec.spec == 'E' || spec.spec == 'G';
1179   const int spec_g = spec.spec == 'g' || spec.spec == 'G';
1180   const int keep_trailing_zeros = (spec_g && spec.alt)
1181     || (!spec_g && (spec.prec > 0));
1182
1183   /* sign */
1184   if (MPFR_IS_NEG (p))
1185     np->sign = '-';
1186   else if (spec.showsign || spec.space)
1187     np->sign = spec.showsign ? '+' : ' ';
1188
1189   /* integral part */
1190   np->ip_size = 1;
1191   {
1192     size_t nsd;
1193
1194     /* Number of significant digits:
1195        - if no given precision, then let mpfr_get_str determine it,
1196        - if a precision is specified, then one digit before decimal point
1197        plus SPEC.PREC after it.
1198        We use the fact here that mpfr_get_str allows us to ask for only one
1199        significant digit when the base is not a power of 2. */
1200     nsd = (spec.prec < 0) ? 0 : spec.prec + np->ip_size;
1201     str = mpfr_get_str (0, &exp, 10, nsd, p, spec.rnd_mode);
1202   }
1203   register_string (np->sl, str);
1204   np->ip_ptr = MPFR_IS_NEG (p) ? ++str : str;  /* skip sign if any */
1205
1206   if (spec.prec != 0)
1207     /* compute the number of digits in fractional part */
1208     {
1209       char *ptr;
1210       size_t str_len;
1211
1212       /* the sign has been skipped, skip also the first digit */
1213       ++str;
1214       str_len = strlen (str);
1215       ptr = str + str_len - 1; /* points to the end of str */
1216
1217       if (!keep_trailing_zeros)
1218         /* remove trailing zeros, if any */
1219         {
1220           while ((*ptr == '0') && (str_len != 0))
1221             {
1222               --ptr;
1223               --str_len;
1224             }
1225         }
1226
1227       if (str_len > INT_MAX)
1228         /* too many digits in fractional part */
1229         return -1;
1230
1231       if (str_len != 0)
1232         /* there are some non-zero digits in fractional part */
1233         {
1234           np->fp_ptr = str;
1235           np->fp_size = str_len;
1236           if ((!spec_g || spec.alt) && (spec.prec > 0)
1237               && ((int)str_len < spec.prec))
1238             /* add missing trailing zeros */
1239             np->fp_trailing_zeros = spec.prec - str_len;
1240         }
1241     }
1242
1243   /* decimal point */
1244   if (np->fp_size != 0 || spec.alt)
1245     np->point = MPFR_DECIMAL_POINT;
1246
1247   /* EXP is the exponent for decimal point BEFORE the first digit, we want
1248      the exponent for decimal point AFTER the first digit.
1249      Here, no possible overflow because exp < MPFR_EXP (p) / 3 */
1250   exp--;
1251
1252   /* the exponent part contains the character 'e', or 'E' plus the sign
1253      character plus at least two digits and only as many more digits as
1254      necessary to represent the exponent.
1255      We assume that |EXP| < 10^INT_MAX. */
1256   np->exp_size = 3;
1257   {
1258     mp_exp_unsigned_t x;
1259
1260     x = SAFE_ABS (mp_exp_unsigned_t, exp);
1261     while (x > 9)
1262       {
1263         np->exp_size++;
1264         x /= 10;
1265       }
1266   }
1267   if (np->exp_size < 4)
1268     np->exp_size = 4;
1269
1270   str = (char *) (*__gmp_allocate_func) (1 + np->exp_size);
1271   np->exp_ptr = register_string (np->sl, str);
1272
1273   {
1274     char exp_fmt[8];  /* e.g. "e%+.2i", or "E%+.2li" */
1275
1276     exp_fmt[0] = uppercase ? 'E' : 'e';
1277     exp_fmt[1] = '\0';
1278     strcat (exp_fmt, "%+.2" MPFR_EXP_FORMAT_SPEC);
1279
1280     if (sprintf (str, exp_fmt, exp) < 0)
1281       return -1;
1282   }
1283
1284   return 0;
1285 }
1286
1287 /* Determine the different parts of the string representation of the regular
1288    number P when SPEC.SPEC is 'f', 'F', 'g', or 'G'.
1289
1290    return -1 if some field of number_parts is greater than INT_MAX */
1291 static int
1292 regular_fg (struct number_parts *np, mpfr_srcptr p,
1293             const struct printf_spec spec)
1294 {
1295   mp_exp_t exp;
1296   char * str;
1297   const int spec_g = (spec.spec == 'g' || spec.spec == 'G');
1298   const int keep_trailing_zeros = spec_g && spec.alt;
1299
1300   /* WARNING: an empty precision field is forbidden (it means precision = 6
1301      and it should have been changed to 6 before the function call) */
1302   MPFR_ASSERTD (spec.prec >= 0);
1303
1304   /* sign */
1305   if (MPFR_IS_NEG (p))
1306     np->sign = '-';
1307   else if (spec.showsign || spec.space)
1308     np->sign = spec.showsign ? '+' : ' ';
1309
1310   if (MPFR_GET_EXP (p) <= 0)
1311     /* 0 < |p| < 1 */
1312     {
1313       /* Most of the time, integral part is 0 */
1314       np->ip_size = 1;
1315       str = (char *) (*__gmp_allocate_func) (1 + np->ip_size);
1316       str[0] = '0';
1317       str[1] = '\0';
1318       np->ip_ptr = register_string (np->sl, str);
1319
1320       if (spec.prec == 0)
1321         /* only two possibilities: either 1 or 0. */
1322         {
1323           mpfr_t y;
1324           /* y = abs(p) */
1325           MPFR_ALIAS (y, p, 1, MPFR_EXP (p));
1326
1327           if ((spec.rnd_mode == GMP_RNDD && MPFR_IS_NEG (p))
1328               || (spec.rnd_mode == GMP_RNDU && MPFR_IS_POS (p))
1329               || (spec.rnd_mode == GMP_RNDN && mpfr_cmp_d (y, 0.5) > 0))
1330             /* rounded up to 1: one digit '1' in integral part.
1331                note that 0.5 is rounded to 0 with RNDN (round ties to even) */
1332             np->ip_ptr[0] = '1';
1333         }
1334       else
1335         {
1336           /* exp =  position of the most significant decimal digit. */
1337           round_to_10_power (&exp, p, 0, GMP_RNDZ);
1338           MPFR_ASSERTD (exp < 0);
1339
1340           if (exp < -spec.prec)
1341             /* only the last digit may be non zero */
1342             {
1343               int round_away;
1344               switch (spec.rnd_mode)
1345                 {
1346                 case GMP_RNDD:
1347                   round_away = MPFR_IS_NEG (p);
1348                   break;
1349                 case GMP_RNDU:
1350                   round_away = MPFR_IS_POS (p);
1351                   break;
1352                 case GMP_RNDN:
1353                   {
1354                     /* compare |p| to y = 0.5*10^(-spec.prec) */
1355                     mpfr_t y;
1356                     mp_exp_t e = MAX (MPFR_PREC (p), 56);
1357                     mpfr_init2 (y, e + 8);
1358                     do
1359                       {
1360                         /* find a lower approximation of
1361                            0.5*10^(-spec.prec) different from |p| */
1362                         e += 8;
1363                         mpfr_set_prec (y, e);
1364                         mpfr_set_si (y, -spec.prec, GMP_RNDN);
1365                         mpfr_exp10 (y, y, GMP_RNDD);
1366                         mpfr_div_2ui (y, y, 1, GMP_RNDN);
1367                       } while (mpfr_cmpabs (y, p) == 0);
1368
1369                     round_away = mpfr_cmpabs (y, p) < 0;
1370                     mpfr_clear (y);
1371                   }
1372                   break;
1373                 default:
1374                   round_away = 0;
1375                 }
1376
1377               if (round_away)
1378                 /* round away from zero: the last output digit is '1' */
1379                 {
1380                   np->fp_leading_zeros = spec.prec - 1;
1381
1382                   np->fp_size = 1;
1383                   str =
1384                     (char *) (*__gmp_allocate_func) (1 + np->fp_size);
1385                   str[0] = '1';
1386                   str[1] = '\0';
1387                   np->fp_ptr = register_string (np->sl, str);
1388                 }
1389               else
1390                 /* only zeros in fractional part */
1391                 {
1392                   MPFR_ASSERTD (!spec_g);
1393                   np->fp_leading_zeros = spec.prec;
1394                 }
1395             }
1396           else
1397             /* the most significant digits are the last
1398                spec.prec + exp + 1 digits in fractional part */
1399             {
1400               char *ptr;
1401               size_t str_len;
1402               size_t nsd = spec.prec + exp + 1;
1403               /* WARNING: nsd may equal 1, but here we use the fact that
1404                  mpfr_get_str can return one digit with base ten
1405                  (undocumented feature, see comments in get_str.c) */
1406
1407               str = mpfr_get_str (NULL, &exp, 10, nsd, p, spec.rnd_mode);
1408               register_string (np->sl, str);
1409               if (MPFR_IS_NEG (p))
1410                 ++str;
1411               if (exp == 1)
1412                 /* round up to 1 */
1413                 {
1414                   MPFR_ASSERTD (str[0] == '1');
1415                   np->ip_ptr[0] = '1';
1416                   if (!spec_g || spec.alt)
1417                     np->fp_leading_zeros = spec.prec;
1418                 }
1419               else
1420                 {
1421                   /* skip sign */
1422                   np->fp_ptr = str;
1423                   np->fp_leading_zeros = -exp;
1424                   MPFR_ASSERTD (exp <= 0);
1425
1426                   str_len = strlen (str); /* the sign has been skipped */
1427                   ptr = str + str_len - 1; /* points to the end of str */
1428
1429                   if (!keep_trailing_zeros)
1430                     /* remove trailing zeros, if any */
1431                     {
1432                       while ((*ptr == '0') && str_len)
1433                         {
1434                           --ptr;
1435                           --str_len;
1436                         }
1437                     }
1438
1439                   if (str_len > INT_MAX)
1440                     /* too many digits in fractional part */
1441                     return -1;
1442
1443                   MPFR_ASSERTD (str_len > 0);
1444                   np->fp_size = str_len;
1445
1446                   if ((!spec_g || spec.alt)
1447                       && spec.prec > 0
1448                       && (np->fp_leading_zeros + np->fp_size < spec.prec))
1449                     /* add missing trailing zeros */
1450                     np->fp_trailing_zeros = spec.prec - np->fp_leading_zeros
1451                       - np->fp_size;
1452                 }
1453             }
1454         }
1455
1456       if (spec.alt || np->fp_leading_zeros != 0 || np->fp_size != 0
1457           || np->fp_trailing_zeros != 0)
1458         np->point = MPFR_DECIMAL_POINT;
1459     }
1460   else
1461     /* 1 <= |p| */
1462     {
1463       size_t nsd;  /* Number of significant digits */
1464
1465       /* Determine the position of the most significant decimal digit. */
1466       round_to_10_power (&exp, p, 0, GMP_RNDZ);
1467
1468       MPFR_ASSERTD (exp >= 0);
1469       if (exp > INT_MAX)
1470         /* P is too large to print all its integral part digits */
1471         return -1;
1472
1473       np->ip_size = exp + 1;
1474
1475       nsd = spec.prec + np->ip_size;
1476       str = mpfr_get_str (NULL, &exp, 10, nsd, p, spec.rnd_mode);
1477       register_string (np->sl, str);
1478       np->ip_ptr = MPFR_IS_NEG (p) ? ++str : str; /* skip sign */
1479
1480       if (spec.group)
1481         /* thousands separator in integral part */
1482         np->thousands_sep = MPFR_THOUSANDS_SEPARATOR;
1483
1484       if (nsd == 0 || (spec_g && !spec.alt))
1485         /* compute how much non-zero digits in integral and fractional
1486            parts */
1487         {
1488           size_t str_len;
1489           str_len = strlen (str); /* note: the sign has been skipped */
1490
1491           if (exp > str_len)
1492             /* mpfr_get_str doesn't give the trailing zeros when p is a
1493                multiple of 10 (p integer, so no fractional part) */
1494             {
1495               np->ip_trailing_zeros = exp - str_len;
1496               np->ip_size = str_len;
1497               if (spec.alt)
1498                 np->point = MPFR_DECIMAL_POINT;
1499             }
1500           else
1501             /* str may contain some digits which are in fractional part */
1502             {
1503               char *ptr;
1504
1505               ptr = str + str_len - 1; /* points to the end of str */
1506               str_len -= np->ip_size;  /* number of digits in fractional
1507                                           part */
1508
1509               if (!keep_trailing_zeros)
1510                 /* remove trailing zeros, if any */
1511                 {
1512                   while ((*ptr == '0') && (str_len != 0))
1513                     {
1514                       --ptr;
1515                       --str_len;
1516                     }
1517                 }
1518
1519               if (str_len > INT_MAX)
1520                 /* too many digits in fractional part */
1521                 return -1;
1522
1523               if (str_len != 0)
1524                 /* some digits in fractional part */
1525                 {
1526                   np->point = MPFR_DECIMAL_POINT;
1527                   np->fp_ptr = str + np->ip_size;
1528                   np->fp_size = str_len;
1529                 }
1530             }
1531         }
1532       else
1533         /* spec.prec digits in fractional part */
1534         {
1535           if (np->ip_size == exp - 1)
1536             /* the absolute value of the number has been rounded up to a power
1537                of ten.
1538                Insert an additional zero in integral part and put the rest of
1539                them in fractional part. */
1540             np->ip_trailing_zeros = 1;
1541
1542           if (spec.prec != 0)
1543             {
1544               MPFR_ASSERTD (np->ip_size + np->ip_trailing_zeros == exp);
1545               MPFR_ASSERTD (np->ip_size + spec.prec == nsd);
1546
1547               np->point = MPFR_DECIMAL_POINT;
1548               np->fp_ptr = str + np->ip_size;
1549               np->fp_size = spec.prec;
1550             }
1551           else if (spec.alt)
1552             np->point = MPFR_DECIMAL_POINT;
1553         }
1554     }
1555
1556   return 0;
1557 }
1558
1559 /* partition_number determines the different parts of the string
1560    representation of the number p according to the given specification.
1561    partition_number initializes the given structure np, so all previous
1562    information in that variable is lost.
1563    return the total number of characters to be written.
1564    return -1 if an error occured, in that case np's fields are in an undefined
1565    state but all string buffers have been freed. */
1566 static int
1567 partition_number (struct number_parts *np, mpfr_srcptr p,
1568                   struct printf_spec spec)
1569 {
1570   char *str;
1571   long total;
1572   int uppercase;
1573
1574   /* WARNING: left justification means right space padding */
1575   np->pad_type = spec.left ? RIGHT : spec.pad == '0' ? LEADING_ZEROS : LEFT;
1576   np->pad_size = 0;
1577   np->sign = '\0';
1578   np->prefix_ptr =NULL;
1579   np->prefix_size = 0;
1580   np->thousands_sep = '\0';
1581   np->ip_ptr = NULL;
1582   np->ip_size = 0;
1583   np->ip_trailing_zeros = 0;
1584   np->point = '\0';
1585   np->fp_leading_zeros = 0;
1586   np->fp_ptr = NULL;
1587   np->fp_size = 0;
1588   np->fp_trailing_zeros = 0;
1589   np->exp_ptr = NULL;
1590   np->exp_size = 0;
1591   np->sl = (struct string_list *)
1592     (*__gmp_allocate_func) (sizeof (struct string_list));
1593   init_string_list (np->sl);
1594
1595   uppercase = spec.spec == 'A' || spec.spec == 'E' || spec.spec == 'F'
1596     || spec.spec == 'G';
1597
1598   if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (p)))
1599     {
1600       if (MPFR_IS_NAN (p))
1601         {
1602           if (np->pad_type == LEADING_ZEROS)
1603             /* don't want "0000nan", change to right justification padding
1604                with left spaces instead */
1605             np->pad_type = LEFT;
1606
1607           if (uppercase)
1608             {
1609               np->ip_size = MPFR_NAN_STRING_LENGTH;
1610               str = (char *) (*__gmp_allocate_func) (1 + np->ip_size);
1611               strcpy (str, MPFR_NAN_STRING_UC);
1612               np->ip_ptr = register_string (np->sl, str);
1613             }
1614           else
1615             {
1616               np->ip_size = MPFR_NAN_STRING_LENGTH;
1617               str = (char *) (*__gmp_allocate_func) (1 + np->ip_size);
1618               strcpy (str, MPFR_NAN_STRING_LC);
1619               np->ip_ptr = register_string (np->sl, str);
1620             }
1621         }
1622       else if (MPFR_IS_INF (p))
1623         {
1624           if (np->pad_type == LEADING_ZEROS)
1625             /* don't want "0000inf", change to right justification padding
1626                with left spaces instead */
1627             np->pad_type = LEFT;
1628
1629           if (MPFR_IS_NEG (p))
1630             np->sign = '-';
1631
1632           if (uppercase)
1633             {
1634               np->ip_size = MPFR_INF_STRING_LENGTH;
1635               str = (char *) (*__gmp_allocate_func) (1 + np->ip_size);
1636               strcpy (str, MPFR_INF_STRING_UC);
1637               np->ip_ptr = register_string (np->sl, str);
1638             }
1639           else
1640             {
1641               np->ip_size = MPFR_INF_STRING_LENGTH;
1642               str = (char *) (*__gmp_allocate_func) (1 + np->ip_size);
1643               strcpy (str, MPFR_INF_STRING_LC);
1644               np->ip_ptr = register_string (np->sl, str);
1645             }
1646         }
1647       else
1648         /* p == 0 */
1649         {
1650           /* note: for 'g' spec, zero is always displayed with 'f'-style with
1651              precision spec.prec - 1 and the trailing zeros are removed unless
1652              the flag '#' is used. */
1653           if (MPFR_IS_NEG (p))
1654             /* signed zero */
1655             np->sign = '-';
1656           else if (spec.showsign || spec.space)
1657             np->sign = spec.showsign ? '+' : ' ';
1658
1659           if (spec.spec == 'a' || spec.spec == 'A')
1660             /* prefix part */
1661             {
1662               np->prefix_size = 2;
1663               str = (char *) (*__gmp_allocate_func) (1 + np->prefix_size);
1664               str[0] = '0';
1665               str[1] = uppercase ? 'X' : 'x';
1666               str[2] = '\0';
1667               np->prefix_ptr = register_string (np->sl, str);
1668             }
1669
1670           /* integral part */
1671           np->ip_size = 1;
1672           str = (char *) (*__gmp_allocate_func) (1 + np->ip_size);
1673           str[0] = '0';
1674           str[1] = '\0';
1675           np->ip_ptr = register_string (np->sl, str);
1676
1677           if (spec.prec > 0
1678               && ((spec.spec != 'g' && spec.spec != 'G') || spec.alt))
1679             /* fractional part */
1680             {
1681               np->point = MPFR_DECIMAL_POINT;
1682               np->fp_trailing_zeros = (spec.spec == 'g' && spec.spec == 'G') ?
1683                 spec.prec - 1 : spec.prec;
1684             }
1685           else if (spec.alt)
1686             np->point = MPFR_DECIMAL_POINT;
1687
1688           if (spec.spec == 'a' || spec.spec == 'A' || spec.spec == 'b'
1689               || spec.spec == 'e' || spec.spec == 'E')
1690             /* exponent part */
1691             {
1692               np->exp_size = (spec.spec == 'e' || spec.spec == 'E') ? 4 : 3;
1693               str = (char *) (*__gmp_allocate_func) (1 + np->exp_size);
1694               if (spec.spec == 'e' || spec.spec == 'E')
1695                 strcpy (str, uppercase ? "E+00" : "e+00");
1696               else
1697                 strcpy (str, uppercase ? "P+0" : "p+0");
1698               np->exp_ptr = register_string (np->sl, str);
1699             }
1700         }
1701     }
1702   else
1703     /* regular p, p != 0 */
1704     {
1705       if (spec.spec == 'a' || spec.spec == 'A' || spec.spec == 'b')
1706         {
1707           if (regular_ab (np, p, spec) == -1)
1708             goto error;
1709         }
1710       else if (spec.spec == 'f' || spec.spec == 'F')
1711         {
1712           if (spec.prec == -1)
1713             spec.prec = 6;
1714           if (regular_fg (np, p, spec) == -1)
1715             goto error;
1716         }
1717       else if (spec.spec == 'e' || spec.spec == 'E')
1718         {
1719           if (regular_eg (np, p, spec) == -1)
1720             goto error;
1721         }
1722       else
1723         /* %g case */
1724         {
1725           /* Use the C99 rules:
1726              if T > X >= -4 then the conversion is with style 'f'/'F' and
1727              precision T-(X+1).
1728              otherwise, the conversion is with style 'e'/'E' and
1729              precision T-1.
1730              where T is the threshold computed below and X is the exponent
1731              that would be displayed with style 'e' and precision T-1. */
1732           int threshold;
1733           mp_exp_t x;
1734
1735           threshold = (spec.prec < 0) ? 6 : (spec.prec == 0) ? 1 : spec.prec;
1736           round_to_10_power (&x, p, threshold - 1, spec.rnd_mode);
1737
1738           if (threshold > x && x >= -4)
1739             {
1740               /* the conversion is with style 'f' */
1741               spec.prec = threshold - x - 1;
1742
1743               if (regular_fg (np, p, spec) == -1)
1744                 goto error;
1745             }
1746           else
1747             {
1748               spec.prec = threshold - 1;
1749
1750               if (regular_eg (np, p, spec) == -1)
1751                 goto error;
1752             }
1753         }
1754     }
1755
1756   /* compute the number of characters to be written verifying it is not too
1757      much */
1758   total = np->sign ? 1 : 0;
1759   total += np->prefix_size;
1760   total += np->ip_size;
1761   if (MPFR_UNLIKELY (total < 0 || total > INT_MAX))
1762     goto error;
1763   total += np->ip_trailing_zeros;
1764   if (MPFR_UNLIKELY (total < 0 || total > INT_MAX))
1765     goto error;
1766   if (np->thousands_sep)
1767     /* ' flag, style f and the thousands separator in current locale is not
1768        reduced to the null character */
1769     total += (np->ip_size + np->ip_trailing_zeros) / 3;
1770   if (MPFR_UNLIKELY (total < 0 || total > INT_MAX))
1771     goto error;
1772   if (np->point)
1773     ++total;
1774   total += np->fp_leading_zeros;
1775   if (MPFR_UNLIKELY (total < 0 || total > INT_MAX))
1776     goto error;
1777   total += np->fp_size;
1778   if (MPFR_UNLIKELY (total < 0 || total > INT_MAX))
1779     goto error;
1780   total += np->fp_trailing_zeros;
1781   if (MPFR_UNLIKELY (total < 0 || total > INT_MAX))
1782     goto error;
1783   total += np->exp_size;
1784   if (MPFR_UNLIKELY (total < 0 || total > INT_MAX))
1785     goto error;
1786
1787   if (spec.width > total)
1788     /* pad with spaces or zeros depending on np->pad_type */
1789     {
1790       np->pad_size = spec.width - total;
1791       total += np->pad_size; /* here total == spec.width,
1792                                 so 0 < total < INT_MAX */
1793     }
1794
1795   return total;
1796
1797  error:
1798   clear_string_list (np->sl);
1799   np->prefix_ptr = NULL;
1800   np->ip_ptr = NULL;
1801   np->fp_ptr = NULL;
1802   np->exp_ptr = NULL;
1803   return -1;
1804 }
1805
1806 /* sprnt_fp prints a mpfr_t according to spec.spec specification.
1807
1808    return the size of the string (not counting the terminating '\0')
1809    return -1 if the built string is too long (i.e. has more than
1810    INT_MAX characters). */
1811 static int
1812 sprnt_fp (struct string_buffer *buf, mpfr_srcptr p,
1813           const struct printf_spec spec)
1814 {
1815   int length;
1816   struct number_parts np;
1817
1818   length = partition_number (&np, p, spec);
1819   if (length < 0)
1820     return -1;
1821
1822   /* right justification padding with left spaces */
1823   if (np.pad_type == LEFT && np.pad_size != 0)
1824     buffer_pad (buf, ' ', np.pad_size);
1825
1826   /* sign character (may be '-', '+', or ' ') */
1827   if (np.sign)
1828     buffer_pad (buf, np.sign, 1);
1829
1830   /* prefix part */
1831   if (np.prefix_ptr)
1832     buffer_cat (buf, np.prefix_ptr, np.prefix_size);
1833
1834   /* right justification  padding with leading zeros */
1835   if (np.pad_type == LEADING_ZEROS && np.pad_size != 0)
1836     buffer_pad (buf, '0', np.pad_size);
1837
1838   /* integral part (may also be "nan" or "inf") */
1839   MPFR_ASSERTN (np.ip_ptr != NULL); /* never empty */
1840   if (MPFR_UNLIKELY (np.thousands_sep))
1841     buffer_sandwich (buf, np.ip_ptr, np.ip_size, np.ip_trailing_zeros,
1842                      np.thousands_sep);
1843   else
1844     {
1845       buffer_cat (buf, np.ip_ptr, np.ip_size);
1846
1847       /* trailing zeros in integral part */
1848       if (np.ip_trailing_zeros != 0)
1849         buffer_pad (buf, '0', np.ip_trailing_zeros);
1850     }
1851
1852   /* decimal point */
1853   if (np.point)
1854     buffer_pad (buf, np.point, 1);
1855
1856   /* leading zeros in fractional part */
1857   if (np.fp_leading_zeros != 0)
1858     buffer_pad (buf, '0', np.fp_leading_zeros);
1859
1860   /* significant digits in fractional part */
1861   if (np.fp_ptr)
1862     buffer_cat (buf, np.fp_ptr, np.fp_size);
1863
1864   /* trailing zeros in fractional part */
1865   if (np.fp_trailing_zeros != 0)
1866     buffer_pad (buf, '0', np.fp_trailing_zeros);
1867
1868   /* exponent part */
1869   if (np.exp_ptr)
1870     buffer_cat (buf, np.exp_ptr, np.exp_size);
1871
1872   /* left justication padding with right spaces */
1873   if (np.pad_type == RIGHT && np.pad_size != 0)
1874     buffer_pad (buf, ' ', np.pad_size);
1875
1876   clear_string_list (np.sl);
1877   return length;
1878 }
1879
1880 int
1881 mpfr_vasprintf (char **ptr, const char *fmt, va_list ap)
1882 {
1883   struct string_buffer buf;
1884   size_t nbchar;
1885
1886   /* informations on the conversion specification filled by the parser */
1887   struct printf_spec spec;
1888   /* flag raised when previous part of fmt need to be processed by
1889      gmp_vsnprintf */
1890   int xgmp_fmt_flag;
1891   /* beginning and end of the previous unprocessed part of fmt */
1892   const char *start, *end;
1893   /* pointer to arguments for gmp_vasprintf */
1894   va_list ap2;
1895
1896   MPFR_SAVE_EXPO_DECL (expo);
1897   MPFR_SAVE_EXPO_MARK (expo);
1898
1899   nbchar = 0;
1900   buffer_init (&buf, 4096 * sizeof (char));
1901   xgmp_fmt_flag = 0;
1902   va_copy (ap2, ap);
1903   start = fmt;
1904   while (*fmt)
1905     {
1906       /* Look for the next format specification */
1907       while ((*fmt) && (*fmt != '%'))
1908         ++fmt;
1909
1910       if (*fmt == '\0')
1911         break;
1912
1913       if (*++fmt == '%')
1914         /* %%: go one step further otherwise the second '%' would be
1915            considered as a new conversion specification introducing
1916            character */
1917         {
1918           ++fmt;
1919           xgmp_fmt_flag = 1;
1920           continue;
1921         }
1922
1923       end = fmt - 1;
1924
1925       /* format string analysis */
1926       specinfo_init (&spec);
1927       fmt = parse_flags (fmt, &spec);
1928
1929       READ_INT (ap, fmt, spec, width, width_analysis);
1930     width_analysis:
1931       if (spec.width < 0)
1932         {
1933           spec.left = 1;
1934           spec.width = -spec.width;
1935           MPFR_ASSERTN (spec.width < INT_MAX);
1936         }
1937       if (*fmt == '.')
1938         {
1939           const char *f = ++fmt;
1940           READ_INT (ap, fmt, spec, prec, prec_analysis);
1941         prec_analysis:
1942           if (f == fmt)
1943             spec.prec = -1;
1944         }
1945       else
1946         spec.prec = -1;
1947
1948       fmt = parse_arg_type (fmt, &spec);
1949       if (spec.arg_type == UNSUPPORTED)
1950         /* the current architecture doesn't support this type */
1951         {
1952           goto error;
1953         }
1954       else if (spec.arg_type == MPFR_ARG)
1955         {
1956           switch (*fmt)
1957             {
1958             case '\0':
1959               break;
1960             case '*':
1961               ++fmt;
1962               spec.rnd_mode = (mpfr_rnd_t) va_arg (ap, int);
1963               break;
1964             case 'D':
1965               ++fmt;
1966               spec.rnd_mode = GMP_RNDD;
1967               break;
1968             case 'U':
1969               ++fmt;
1970               spec.rnd_mode = GMP_RNDU;
1971               break;
1972             case 'Z':
1973               ++fmt;
1974               spec.rnd_mode = GMP_RNDZ;
1975               break;
1976             case 'N':
1977               ++fmt;
1978             default:
1979               spec.rnd_mode = GMP_RNDN;
1980             }
1981         }
1982
1983       spec.spec = *fmt;
1984       if (!specinfo_is_valid (spec))
1985         goto error;
1986
1987       if (*fmt)
1988         fmt++;
1989
1990       /* Format processing */
1991       if (spec.spec == '\0')
1992         /* end of the format string */
1993         break;
1994       else if (spec.spec == 'n')
1995         /* put the number of characters written so far in the location pointed
1996            by the next va_list argument; the types of pointer accepted are the
1997            same as in GMP (except unsupported quad_t) plus pointer to a mpfr_t
1998            so as to be able to accept the same format strings. */
1999         {
2000           void *p;
2001           size_t nchar;
2002
2003           p = va_arg (ap, void *);
2004           FLUSH (xgmp_fmt_flag, start, end, ap2, &buf);
2005           va_end (ap2);
2006           start = fmt;
2007           nchar = buf.curr - buf.start;
2008
2009           switch (spec.arg_type)
2010             {
2011             case CHAR_ARG:
2012               *(char *) p = (char) nchar;
2013               break;
2014             case SHORT_ARG:
2015               *(short *) p = (short) nchar;
2016               break;
2017             case LONG_ARG:
2018               *(long *) p = (long) nchar;
2019               break;
2020 #ifdef HAVE_LONG_LONG
2021             case LONG_LONG_ARG:
2022               *(long long *) p = (long long) nchar;
2023               break;
2024 #endif
2025 #ifdef _MPFR_H_HAVE_INTMAX_T
2026             case INTMAX_ARG:
2027               *(intmax_t *) p = (intmax_t) nchar;
2028               break;
2029 #endif
2030             case SIZE_ARG:
2031               *(size_t *) p = nchar;
2032               break;
2033             case PTRDIFF_ARG:
2034               *(ptrdiff_t *) p = (ptrdiff_t) nchar;
2035               break;
2036             case MPF_ARG:
2037               mpf_set_ui ((mpf_ptr) p, (unsigned long) nchar);
2038               break;
2039             case MPQ_ARG:
2040               mpq_set_ui ((mpq_ptr) p, (unsigned long) nchar, 1L);
2041               break;
2042             case MP_LIMB_ARG:
2043               *(mp_limb_t *) p = (mp_limb_t) nchar;
2044               break;
2045             case MP_LIMB_ARRAY_ARG:
2046               {
2047                 mp_limb_t *q = (mp_limb_t *) p;
2048                 mp_size_t n;
2049                 n = va_arg (ap, mp_size_t);
2050                 if (n < 0)
2051                   n = -n;
2052                 else if (n == 0)
2053                   break;
2054
2055                 /* we assume here that mp_limb_t is wider than int */
2056                 *q = (mp_limb_t) nchar;
2057                 while (--n != 0)
2058                   {
2059                     q++;
2060                     *q = (mp_limb_t) 0;
2061                   }
2062               }
2063               break;
2064             case MPZ_ARG:
2065               mpz_set_ui ((mpz_ptr) p, (unsigned long) nchar);
2066               break;
2067
2068             case MPFR_ARG:
2069               mpfr_set_ui ((mpfr_ptr) p, (unsigned long) nchar,
2070                            spec.rnd_mode);
2071               break;
2072
2073             default:
2074               *(int *) p = (int) nchar;
2075             }
2076           va_copy (ap2, ap); /* after the switch, due to MP_LIMB_ARRAY_ARG
2077                                 case */
2078         }
2079       else if (spec.arg_type == MPFR_PREC_ARG)
2080         /* output mp_prec_t variable */
2081         {
2082           char *s;
2083           char format[MPFR_PREC_FORMAT_SIZE + 6]; /* see examples below */
2084           size_t length;
2085           mpfr_prec_t prec;
2086           prec = va_arg (ap, mpfr_prec_t);
2087
2088           FLUSH (xgmp_fmt_flag, start, end, ap2, &buf);
2089           va_end (ap2);
2090           va_copy (ap2, ap);
2091           start = fmt;
2092
2093           /* construct format string, like "%*.*hu" "%*.*u" or "%*.*lu" */
2094           format[0] = '%';
2095           format[1] = '*';
2096           format[2] = '.';
2097           format[3] = '*';
2098           format[4] = '\0';
2099           strcat (format, MPFR_PREC_FORMAT_TYPE);
2100           format[4 + MPFR_PREC_FORMAT_SIZE] = spec.spec;
2101           format[5 + MPFR_PREC_FORMAT_SIZE] = '\0';
2102           length = gmp_asprintf (&s, format, spec.width, spec.prec, prec);
2103           if (buf.size <= INT_MAX - length)
2104             {
2105               buffer_cat (&buf, s, length);
2106               mpfr_free_str (s);
2107             }
2108           else
2109             {
2110               mpfr_free_str (s);
2111               goto overflow_error;
2112             }
2113         }
2114       else if (spec.arg_type == MPFR_ARG)
2115         /* output a mpfr_t variable */
2116         {
2117           mpfr_srcptr p;
2118
2119           p = va_arg (ap, mpfr_srcptr);
2120
2121           FLUSH (xgmp_fmt_flag, start, end, ap2, &buf);
2122           va_end (ap2);
2123           va_copy (ap2, ap);
2124           start = fmt;
2125
2126           switch (spec.spec)
2127             {
2128             case 'a':
2129             case 'A':
2130             case 'b':
2131             case 'e':
2132             case 'E':
2133             case 'f':
2134             case 'F':
2135             case 'g':
2136             case 'G':
2137               if (sprnt_fp (&buf, p, spec) < 0)
2138                 goto overflow_error;
2139               break;
2140
2141             default:
2142               /* unsupported specifier */
2143               goto error;
2144             }
2145         }
2146       else
2147         /* gmp_printf specification, step forward in the va_list */
2148         {
2149           CONSUME_VA_ARG (spec, ap);
2150           xgmp_fmt_flag = 1;
2151         }
2152     }
2153
2154   if (start != fmt)
2155     FLUSH (xgmp_fmt_flag, start, fmt, ap2, &buf);
2156
2157   va_end (ap2);
2158   nbchar = buf.curr - buf.start;
2159   MPFR_ASSERTD (nbchar == strlen (buf.start));
2160   buf.start =
2161     (char *) (*__gmp_reallocate_func) (buf.start, buf.size, nbchar + 1);
2162   buf.size = nbchar + 1; /* update needed for __gmp_free_func below when
2163                             nbchar is too large (overflow_error) */
2164   *ptr = buf.start;
2165
2166   /* If nbchar is larger than INT_MAX, the ISO C99 standard is silent, but
2167      POSIX says concerning the snprintf() function:
2168      "[EOVERFLOW] The value of n is greater than {INT_MAX} or the
2169      number of bytes needed to hold the output excluding the
2170      terminating null is greater than {INT_MAX}." See:
2171      http://www.opengroup.org/onlinepubs/009695399/functions/fprintf.html
2172      But it doesn't say anything concerning the other printf-like functions.
2173      A defect report has been submitted to austin-review-l (item 2532).
2174      So, for the time being, we return a negative value and set the erange
2175      flag, and set errno to EOVERFLOW in POSIX system. */
2176   if (nbchar <= INT_MAX)
2177     {
2178       MPFR_SAVE_EXPO_FREE (expo);
2179       return nbchar;
2180     }
2181
2182  overflow_error:
2183   MPFR_SAVE_EXPO_UPDATE_FLAGS(expo, MPFR_FLAGS_ERANGE);
2184 #ifdef EOVERFLOW
2185   errno = EOVERFLOW;
2186 #endif
2187
2188  error:
2189   MPFR_SAVE_EXPO_FREE (expo);
2190   *ptr = NULL;
2191   (*__gmp_free_func) (buf.start, buf.size);
2192
2193   return -1;
2194 }
2195
2196 #endif /* HAVE_STDARG */