2af20a04a131a3fd426edd74755e1fe4018b0b11
[dragonfly.git] / contrib / mpfr / src / printf.c
1 /* mpfr_printf -- printf function and friends.
2
3 Copyright 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
4 Contributed by the Arenaire and Caramel 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 3 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.LESSER.  If not, see
20 http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
21 51 Franklin St, Fifth Floor, Boston, 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> exists */
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 #include <errno.h>
44 #include "mpfr-impl.h"
45
46 #ifdef _MPFR_H_HAVE_FILE
47
48 /* Each printf-like function calls mpfr_vasprintf which
49    - returns the number of characters in the returned string excluding the
50    terminating null
51    - returns -1 and sets the erange flag if the number of produced characters
52    exceeds INT_MAX (in that case, also sets errno to EOVERFLOW in POSIX
53    systems) */
54
55 #define GET_STR_VA(sz, str, fmt, ap)            \
56   do                                            \
57     {                                           \
58       sz = mpfr_vasprintf (&(str), fmt, ap);    \
59       if (sz < 0)                               \
60         {                                       \
61           if (str)                              \
62             mpfr_free_str (str);                \
63           return -1;                            \
64         }                                       \
65     } while (0)
66
67 #define GET_STR(sz, str, fmt)                   \
68   do                                            \
69     {                                           \
70       va_list ap;                               \
71       va_start(ap, fmt);                        \
72       sz = mpfr_vasprintf (&(str), fmt, ap);    \
73       va_end (ap);                              \
74       if (sz < 0)                               \
75         {                                       \
76           if (str)                              \
77             mpfr_free_str (str);                \
78           return -1;                            \
79         }                                       \
80     } while (0)
81
82 int
83 mpfr_printf (const char *fmt, ...)
84 {
85   char *str;
86   int ret;
87
88   GET_STR (ret, str, fmt);
89   ret = printf ("%s", str);
90
91   mpfr_free_str (str);
92   return ret;
93 }
94
95 int
96 mpfr_vprintf (const char *fmt, va_list ap)
97 {
98   char *str;
99   int ret;
100
101   GET_STR_VA (ret, str, fmt, ap);
102   ret = printf ("%s", str);
103
104   mpfr_free_str (str);
105   return ret;
106 }
107
108
109 int
110 mpfr_fprintf (FILE *fp, const char *fmt, ...)
111 {
112   char *str;
113   int ret;
114
115   GET_STR (ret, str, fmt);
116   ret = fprintf (fp, "%s", str);
117
118   mpfr_free_str (str);
119   return ret;
120 }
121
122 int
123 mpfr_vfprintf (FILE *fp, const char *fmt, va_list ap)
124 {
125   char *str;
126   int ret;
127
128   GET_STR_VA (ret, str, fmt, ap);
129   ret = fprintf (fp, "%s", str);
130
131   mpfr_free_str (str);
132   return ret;
133 }
134 #endif /* _MPFR_H_HAVE_FILE */
135
136 int
137 mpfr_sprintf (char *buf, const char *fmt, ...)
138 {
139   char *str;
140   int ret;
141
142   GET_STR (ret, str, fmt);
143   ret = sprintf (buf, "%s", str);
144
145   mpfr_free_str (str);
146   return ret;
147 }
148
149 int
150 mpfr_vsprintf (char *buf, const char *fmt, va_list ap)
151 {
152   char *str;
153   int ret;
154
155   GET_STR_VA (ret, str, fmt, ap);
156   ret = sprintf (buf, "%s", str);
157
158   mpfr_free_str (str);
159   return ret;
160 }
161
162 int
163 mpfr_snprintf (char *buf, size_t size, const char *fmt, ...)
164 {
165   char *str;
166   int ret;
167   size_t min_size;
168
169   GET_STR (ret, str, fmt);
170
171   /* C99 allows SIZE to be zero */
172   if (size != 0)
173     {
174       MPFR_ASSERTN (buf != NULL);
175       min_size = (size_t)ret < size ? (size_t)ret : size - 1;
176       strncpy (buf, str, min_size);
177       buf[min_size] = '\0';
178     }
179
180   mpfr_free_str (str);
181   return ret;
182 }
183
184 int
185 mpfr_vsnprintf (char *buf, size_t size, const char *fmt, va_list ap)
186 {
187   char *str;
188   int ret;
189   int min_size;
190
191   GET_STR_VA (ret, str, fmt, ap);
192
193   /* C99 allows SIZE to be zero */
194   if (size != 0)
195     {
196       MPFR_ASSERTN (buf != NULL);
197       min_size = (size_t)ret < size ? (size_t)ret : size - 1;
198       strncpy (buf, str, min_size);
199       buf[min_size] = '\0';
200     }
201
202   mpfr_free_str (str);
203   return ret;
204 }
205
206 int
207 mpfr_asprintf (char **pp, const char *fmt, ...)
208 {
209   int ret;
210
211   GET_STR (ret, *pp, fmt);
212
213   return ret;
214 }
215 #endif /* HAVE_STDARG */