Upgrade MPFR from 2.4.1 to 2.4.2-p3 on the vendor branch.
[dragonfly.git] / contrib / mpfr / printf.c
1 /* mpfr_printf -- printf function and friends.
2
3 Copyright 2007, 2008, 2009 Free Software Foundation, Inc.
4 Contributed by the Arenaire and Cacao projects, INRIA.
5
6 This file is part of the GNU MPFR Library.
7
8 The GNU MPFR Library is free software; you can redistribute it and/or modify
9 it under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or (at your
11 option) any later version.
12
13 The GNU MPFR Library is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
16 License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with the GNU MPFR Library; see the file COPYING.LIB.  If not, write to
20 the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
21 MA 02110-1301, USA. */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 /* The mpfr_printf-like functions are defined only if stdarg.h exist */
28 #ifdef HAVE_STDARG
29
30 #include <stdarg.h>
31
32 #ifndef HAVE_VA_COPY
33 # ifdef HAVE___VA_COPY
34 #  define va_copy(dst,src) __va_copy(dst, src)
35 # else
36 /* autoconf manual advocates this fallback.
37    This is also the solution chosen by gmp */
38 #  define va_copy(dst,src) \
39   do { memcpy(&(dst), &(src), sizeof(va_list)); } while (0)
40 # endif /* HAVE___VA_COPY */
41 #endif /* HAVE_VA_COPY */
42
43
44 #include <errno.h>
45 #include "mpfr-impl.h"
46
47 #ifdef _MPFR_H_HAVE_FILE
48
49 /* Each printf-like function calls mpfr_vasprintf which
50    - returns the number of characters in the returned string excluding the
51    terminating null
52    - returns -1 and sets the erange flag if the number of produced characters
53    exceeds INT_MAX (in that case, also sets errno to EOVERFLOW in POSIX
54    systems) */
55
56 #define GET_STR_VA(sz, str, fmt, ap)            \
57   do                                            \
58     {                                           \
59       sz = mpfr_vasprintf (&(str), fmt, ap);    \
60       if (sz < 0)                               \
61         {                                       \
62           if (str)                              \
63             mpfr_free_str (str);                \
64           return -1;                            \
65         }                                       \
66     } while (0)
67
68 #define GET_STR(sz, str, fmt)                   \
69   do                                            \
70     {                                           \
71       va_list ap;                               \
72       va_start(ap, fmt);                        \
73       sz = mpfr_vasprintf (&(str), fmt, ap);    \
74       va_end (ap);                              \
75       if (sz < 0)                               \
76         {                                       \
77           if (str)                              \
78             mpfr_free_str (str);                \
79           return -1;                            \
80         }                                       \
81     } while (0)
82
83 int
84 mpfr_printf (const char *fmt, ...)
85 {
86   char *str;
87   int ret;
88
89   GET_STR (ret, str, fmt);
90   ret = printf ("%s", str);
91
92   mpfr_free_str (str);
93   return ret;
94 }
95
96 int
97 mpfr_vprintf (const char *fmt, va_list ap)
98 {
99   char *str;
100   int ret;
101
102   GET_STR_VA (ret, str, fmt, ap);
103   ret = printf ("%s", str);
104
105   mpfr_free_str (str);
106   return ret;
107 }
108
109
110 int
111 mpfr_fprintf (FILE *fp, const char *fmt, ...)
112 {
113   char *str;
114   int ret;
115
116   GET_STR (ret, str, fmt);
117   ret = fprintf (fp, "%s", str);
118
119   mpfr_free_str (str);
120   return ret;
121 }
122
123 int
124 mpfr_vfprintf (FILE *fp, const char *fmt, va_list ap)
125 {
126   char *str;
127   int ret;
128
129   GET_STR_VA (ret, str, fmt, ap);
130   ret = fprintf (fp, "%s", str);
131
132   mpfr_free_str (str);
133   return ret;
134 }
135 #endif /* _MPFR_H_HAVE_FILE */
136
137 int
138 mpfr_sprintf (char *buf, const char *fmt, ...)
139 {
140   char *str;
141   int ret;
142
143   GET_STR (ret, str, fmt);
144   ret = sprintf (buf, "%s", str);
145
146   mpfr_free_str (str);
147   return ret;
148 }
149
150 int
151 mpfr_vsprintf (char *buf, const char *fmt, va_list ap)
152 {
153   char *str;
154   int ret;
155
156   GET_STR_VA (ret, str, fmt, ap);
157   ret = sprintf (buf, "%s", str);
158
159   mpfr_free_str (str);
160   return ret;
161 }
162
163 int
164 mpfr_snprintf (char *buf, size_t size, const char *fmt, ...)
165 {
166   char *str;
167   int ret;
168   size_t min_size;
169
170   GET_STR (ret, str, fmt);
171
172   /* C99 allows SIZE to be zero */
173   if (size != 0)
174     {
175       MPFR_ASSERTN (buf != NULL);
176       min_size = (size_t)ret < size ? (size_t)ret : size - 1;
177       strncpy (buf, str, min_size);
178       buf[min_size] = '\0';
179     }
180
181   mpfr_free_str (str);
182   return ret;
183 }
184
185 int
186 mpfr_vsnprintf (char *buf, size_t size, const char *fmt, va_list ap)
187 {
188   char *str;
189   int ret;
190   int min_size;
191
192   GET_STR_VA (ret, str, fmt, ap);
193
194   /* C99 allows SIZE to be zero */
195   if (size != 0)
196     {
197       MPFR_ASSERTN (buf != NULL);
198       min_size = (size_t)ret < size ? (size_t)ret : size - 1;
199       strncpy (buf, str, min_size);
200       buf[min_size] = '\0';
201     }
202
203   mpfr_free_str (str);
204   return ret;
205 }
206
207 int
208 mpfr_asprintf (char **pp, const char *fmt, ...)
209 {
210   int ret;
211
212   GET_STR (ret, *pp, fmt);
213
214   return ret;
215 }
216 #endif /* HAVE_STDARG */