[BACK]Return to snprntffuns.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / gmp / printf

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>