Annotation of OpenXM_contrib/gmp/printf/snprntffuns.c, Revision 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>