xref: /dragonfly/contrib/mpfr/src/printf.c (revision f2c43266)
1 /* mpfr_printf -- printf function and friends.
2 
3 Copyright 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
4 Contributed by the AriC 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 */
216