1/* mpfr_printf -- printf function and friends.
2
3Copyright 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
4Contributed by the AriC and Caramel projects, INRIA.
5
6This file is part of the GNU MPFR Library.
7
8The GNU MPFR Library is free software; you can redistribute it and/or modify
9it under the terms of the GNU Lesser General Public License as published by
10the Free Software Foundation; either version 3 of the License, or (at your
11option) any later version.
12
13The GNU MPFR Library is distributed in the hope that it will be useful, but
14WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
16License for more details.
17
18You should have received a copy of the GNU Lesser General Public License
19along with the GNU MPFR Library; see the file COPYING.LESSER.  If not, see
20http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
2151 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
82int
83mpfr_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
95int
96mpfr_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
109int
110mpfr_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
122int
123mpfr_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
136int
137mpfr_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
149int
150mpfr_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
162int
163mpfr_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
184int
185mpfr_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
206int
207mpfr_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