Blame printf/doprnti.c

Packit 5c3484
/* __gmp_doprnt_integer -- integer style formatted output.
Packit 5c3484
Packit 5c3484
   THE FUNCTIONS IN THIS FILE ARE FOR INTERNAL USE ONLY.  THEY'RE ALMOST
Packit 5c3484
   CERTAIN TO BE SUBJECT TO INCOMPATIBLE CHANGES OR DISAPPEAR COMPLETELY IN
Packit 5c3484
   FUTURE GNU MP RELEASES.
Packit 5c3484
Packit 5c3484
Copyright 2001 Free Software Foundation, Inc.
Packit 5c3484
Packit 5c3484
This file is part of the GNU MP Library.
Packit 5c3484
Packit 5c3484
The GNU MP Library is free software; you can redistribute it and/or modify
Packit 5c3484
it under the terms of either:
Packit 5c3484
Packit 5c3484
  * the GNU Lesser General Public License as published by the Free
Packit 5c3484
    Software Foundation; either version 3 of the License, or (at your
Packit 5c3484
    option) any later version.
Packit 5c3484
Packit 5c3484
or
Packit 5c3484
Packit 5c3484
  * the GNU General Public License as published by the Free Software
Packit 5c3484
    Foundation; either version 2 of the License, or (at your option) any
Packit 5c3484
    later version.
Packit 5c3484
Packit 5c3484
or both in parallel, as here.
Packit 5c3484
Packit 5c3484
The GNU MP Library is distributed in the hope that it will be useful, but
Packit 5c3484
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
Packit 5c3484
or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
Packit 5c3484
for more details.
Packit 5c3484
Packit 5c3484
You should have received copies of the GNU General Public License and the
Packit 5c3484
GNU Lesser General Public License along with the GNU MP Library.  If not,
Packit 5c3484
see https://www.gnu.org/licenses/.  */
Packit 5c3484
Packit 5c3484
#include <stdarg.h>    /* for va_list and hence doprnt_funs_t */
Packit 5c3484
#include <string.h>
Packit 5c3484
#include <stdio.h>
Packit 5c3484
#include <stdlib.h>
Packit 5c3484
Packit 5c3484
#include "gmp.h"
Packit 5c3484
#include "gmp-impl.h"
Packit 5c3484
Packit 5c3484
Packit 5c3484
int
Packit 5c3484
__gmp_doprnt_integer (const struct doprnt_funs_t *funs,
Packit 5c3484
		      void *data,
Packit 5c3484
		      const struct doprnt_params_t *p,
Packit 5c3484
		      const char *s)
Packit 5c3484
{
Packit 5c3484
  int         retval = 0;
Packit 5c3484
  int         slen, justlen, showbaselen, sign, signlen, slashlen, zeros;
Packit 5c3484
  int         justify, den_showbaselen;
Packit 5c3484
  const char  *slash, *showbase;
Packit 5c3484
Packit 5c3484
  /* '+' or ' ' if wanted, and don't already have '-' */
Packit 5c3484
  sign = p->sign;
Packit 5c3484
  if (s[0] == '-')
Packit 5c3484
    {
Packit 5c3484
      sign = s[0];
Packit 5c3484
      s++;
Packit 5c3484
    }
Packit 5c3484
  signlen = (sign != '\0');
Packit 5c3484
Packit 5c3484
  /* if the precision was explicitly 0, print nothing for a 0 value */
Packit 5c3484
  if (*s == '0' && p->prec == 0)
Packit 5c3484
    s++;
Packit 5c3484
Packit 5c3484
  slen = strlen (s);
Packit 5c3484
  slash = strchr (s, '/');
Packit 5c3484
Packit 5c3484
  showbase = NULL;
Packit 5c3484
  showbaselen = 0;
Packit 5c3484
Packit 5c3484
  if (p->showbase != DOPRNT_SHOWBASE_NO)
Packit 5c3484
    {
Packit 5c3484
      switch (p->base) {
Packit 5c3484
      case 16:  showbase = "0x"; showbaselen = 2; break;
Packit 5c3484
      case -16: showbase = "0X"; showbaselen = 2; break;
Packit 5c3484
      case 8:   showbase = "0";  showbaselen = 1; break;
Packit 5c3484
      }
Packit 5c3484
    }
Packit 5c3484
Packit 5c3484
  den_showbaselen = showbaselen;
Packit 5c3484
  if (slash == NULL
Packit 5c3484
      || (p->showbase == DOPRNT_SHOWBASE_NONZERO && slash[1] == '0'))
Packit 5c3484
    den_showbaselen = 0;
Packit 5c3484
Packit 5c3484
  if (p->showbase == DOPRNT_SHOWBASE_NONZERO && s[0] == '0')
Packit 5c3484
    showbaselen = 0;
Packit 5c3484
Packit 5c3484
  /* the influence of p->prec on mpq is currently undefined */
Packit 5c3484
  zeros = MAX (0, p->prec - slen);
Packit 5c3484
Packit 5c3484
  /* space left over after actual output length */
Packit 5c3484
  justlen = p->width
Packit 5c3484
    - (strlen(s) + signlen + showbaselen + den_showbaselen + zeros);
Packit 5c3484
Packit 5c3484
  justify = p->justify;
Packit 5c3484
  if (justlen <= 0) /* no justifying if exceed width */
Packit 5c3484
    justify = DOPRNT_JUSTIFY_NONE;
Packit 5c3484
Packit 5c3484
  if (justify == DOPRNT_JUSTIFY_RIGHT)             /* pad right */
Packit 5c3484
    DOPRNT_REPS (p->fill, justlen);
Packit 5c3484
Packit 5c3484
  DOPRNT_REPS_MAYBE (sign, signlen);               /* sign */
Packit 5c3484
Packit 5c3484
  DOPRNT_MEMORY_MAYBE (showbase, showbaselen);     /* base */
Packit 5c3484
Packit 5c3484
  DOPRNT_REPS_MAYBE ('0', zeros);                  /* zeros */
Packit 5c3484
Packit 5c3484
  if (justify == DOPRNT_JUSTIFY_INTERNAL)          /* pad internal */
Packit 5c3484
    DOPRNT_REPS (p->fill, justlen);
Packit 5c3484
Packit 5c3484
  /* if there's a showbase on the denominator, then print the numerator
Packit 5c3484
     separately so it can be inserted */
Packit 5c3484
  if (den_showbaselen != 0)
Packit 5c3484
    {
Packit 5c3484
      ASSERT (slash != NULL);
Packit 5c3484
      slashlen = slash+1 - s;
Packit 5c3484
      DOPRNT_MEMORY (s, slashlen);                 /* numerator and slash */
Packit 5c3484
      slen -= slashlen;
Packit 5c3484
      s += slashlen;
Packit 5c3484
      DOPRNT_MEMORY (showbase, den_showbaselen);
Packit 5c3484
    }
Packit 5c3484
Packit 5c3484
  DOPRNT_MEMORY (s, slen);                         /* number, or denominator */
Packit 5c3484
Packit 5c3484
  if (justify == DOPRNT_JUSTIFY_LEFT)              /* pad left */
Packit 5c3484
    DOPRNT_REPS (p->fill, justlen);
Packit 5c3484
Packit 5c3484
 done:
Packit 5c3484
  return retval;
Packit 5c3484
Packit 5c3484
 error:
Packit 5c3484
  retval = -1;
Packit 5c3484
  goto done;
Packit 5c3484
}