Annotation of OpenXM_contrib/gmp/printf/snprntffuns.c, Revision 1.1.1.1
1.1 ohara 1: /* __gmp_snprintf_funs -- support for gmp_snprintf and gmp_vsnprintf.
2:
3: THE FUNCTIONS IN THIS FILE ARE FOR INTERNAL USE ONLY. THEY'RE ALMOST
4: CERTAIN TO BE SUBJECT TO INCOMPATIBLE CHANGES OR DISAPPEAR COMPLETELY IN
5: FUTURE GNU MP RELEASES.
6:
7: Copyright 2001, 2002 Free Software Foundation, Inc.
8:
9: This file is part of the GNU MP Library.
10:
11: The GNU MP Library is free software; you can redistribute it and/or modify
12: it under the terms of the GNU Lesser General Public License as published by
13: the Free Software Foundation; either version 2.1 of the License, or (at your
14: option) any later version.
15:
16: The GNU MP Library is distributed in the hope that it will be useful, but
17: WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18: or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
19: License for more details.
20:
21: You should have received a copy of the GNU Lesser General Public License
22: along with the GNU MP Library; see the file COPYING.LIB. If not, write to
23: the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
24: MA 02111-1307, USA. */
25:
26: #include "config.h"
27:
28: #if HAVE_STDARG
29: #include <stdarg.h>
30: #else
31: #include <varargs.h>
32: #endif
33:
34: #include <stdio.h>
35: #include <string.h>
36:
37: #include "gmp.h"
38: #include "gmp-impl.h"
39:
40:
41: #if ! HAVE_VSNPRINTF
42: #define vsnprintf __gmp_replacement_vsnprintf
43: #endif
44:
45:
46: /* glibc 2.0.x vsnprintf returns either -1 or size-1 for an overflow, with
47: no indication how big the output would have been. It's necessary to
48: re-run to determine that size.
49:
50: "size-1" would mean sucess from a C99 vsnprintf, and the re-run is
51: unnecessary in this case, but we don't bother to try to detect what sort
52: of vsnprintf we've got. size-1 should occur rarely in normal
53: circumstances.
54:
55: vsnprintf might trash it's given ap (it does for instance in glibc 2.1.3
56: on powerpc), so copy it in case we need to use it to probe for the size
57: output that would have been produced. Note there's no need to preserve
58: it for our callers, just for ourselves. */
59:
60: static int
61: gmp_snprintf_format (struct gmp_snprintf_t *d, const char *fmt,
62: va_list orig_ap)
63: {
64: int ret, step, alloc, avail;
65: va_list ap;
66: char *p;
67:
68: ASSERT (d->size >= 0);
69:
70: avail = d->size;
71: if (avail > 1)
72: {
73: va_copy (ap, orig_ap);
74: ret = vsnprintf (d->buf, avail, fmt, ap);
75: if (ret == -1)
76: {
77: ASSERT (strlen (d->buf) == avail-1);
78: ret = avail-1;
79: }
80:
81: step = MIN (ret, avail-1);
82: d->size -= step;
83: d->buf += step;
84:
85: if (ret != avail-1)
86: return ret;
87:
88: /* probably glibc 2.0.x truncated output, probe for actual size */
89: alloc = MAX (128, ret);
90: }
91: else
92: {
93: /* no space to write anything, just probe for size */
94: alloc = 128;
95: }
96:
97: do
98: {
99: alloc *= 2;
100: p = __GMP_ALLOCATE_FUNC_TYPE (alloc, char);
101: va_copy (ap, orig_ap);
102: ret = vsnprintf (p, alloc, fmt, ap);
103: (*__gmp_free_func) (p, alloc);
104: }
105: while (ret == alloc-1 || ret == -1);
106:
107: return ret;
108: }
109:
110: static int
111: gmp_snprintf_memory (struct gmp_snprintf_t *d, const char *str, size_t len)
112: {
113: size_t n;
114:
115: ASSERT (d->size >= 0);
116:
117: if (d->size > 1)
118: {
119: n = MIN (d->size-1, len);
120: memcpy (d->buf, str, n);
121: d->buf += n;
122: d->size -= n;
123: }
124: return len;
125: }
126:
127: static int
128: gmp_snprintf_reps (struct gmp_snprintf_t *d, int c, int reps)
129: {
130: size_t n;
131:
132: ASSERT (reps >= 0);
133: ASSERT (d->size >= 0);
134:
135: if (d->size > 1)
136: {
137: n = MIN (d->size-1, reps);
138: memset (d->buf, c, n);
139: d->buf += n;
140: d->size -= n;
141: }
142: return reps;
143: }
144:
145: static int
146: gmp_snprintf_final (struct gmp_snprintf_t *d)
147: {
148: if (d->size >= 1)
149: d->buf[0] = '\0';
150: return 0;
151: }
152:
153: const struct doprnt_funs_t __gmp_snprintf_funs = {
154: (doprnt_format_t) gmp_snprintf_format,
155: (doprnt_memory_t) gmp_snprintf_memory,
156: (doprnt_reps_t) gmp_snprintf_reps,
157: (doprnt_final_t) gmp_snprintf_final
158: };
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>