Import gmp-4.3.1
[dragonfly.git] / contrib / gmp / printf / doprnti.c
1 /* __gmp_doprnt_integer -- integer style formatted output.
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 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 3 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.  If not, see http://www.gnu.org/licenses/.  */
23
24 #include "config.h"
25
26 #if HAVE_STDARG
27 #include <stdarg.h>    /* for va_list and hence doprnt_funs_t */
28 #else
29 #include <varargs.h>
30 #endif
31
32 #include <string.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35
36 #include "gmp.h"
37 #include "gmp-impl.h"
38
39
40 int
41 __gmp_doprnt_integer (const struct doprnt_funs_t *funs,
42                       void *data,
43                       const struct doprnt_params_t *p,
44                       const char *s)
45 {
46   int         retval = 0;
47   int         slen, justlen, showbaselen, sign, signlen, slashlen, zeros;
48   int         justify, den_showbaselen;
49   const char  *slash, *showbase;
50
51   /* '+' or ' ' if wanted, and don't already have '-' */
52   sign = p->sign;
53   if (s[0] == '-')
54     {
55       sign = s[0];
56       s++;
57     }
58   signlen = (sign != '\0');
59
60   /* if the precision was explicitly 0, print nothing for a 0 value */
61   if (*s == '0' && p->prec == 0)
62     s++;
63
64   slen = strlen (s);
65   slash = strchr (s, '/');
66
67   showbase = NULL;
68   showbaselen = 0;
69
70   if (p->showbase != DOPRNT_SHOWBASE_NO)
71     {
72       switch (p->base) {
73       case 16:  showbase = "0x"; showbaselen = 2; break;
74       case -16: showbase = "0X"; showbaselen = 2; break;
75       case 8:   showbase = "0";  showbaselen = 1; break;
76       }
77     }
78
79   den_showbaselen = showbaselen;
80   if (slash == NULL
81       || (p->showbase == DOPRNT_SHOWBASE_NONZERO && slash[1] == '0'))
82     den_showbaselen = 0;
83
84   if (p->showbase == DOPRNT_SHOWBASE_NONZERO && s[0] == '0')
85     showbaselen = 0;
86
87   /* the influence of p->prec on mpq is currently undefined */
88   zeros = MAX (0, p->prec - slen);
89
90   /* space left over after actual output length */
91   justlen = p->width
92     - (strlen(s) + signlen + showbaselen + den_showbaselen + zeros);
93
94   justify = p->justify;
95   if (justlen <= 0) /* no justifying if exceed width */
96     justify = DOPRNT_JUSTIFY_NONE;
97
98   if (justify == DOPRNT_JUSTIFY_RIGHT)             /* pad right */
99     DOPRNT_REPS (p->fill, justlen);
100
101   DOPRNT_REPS_MAYBE (sign, signlen);               /* sign */
102
103   DOPRNT_MEMORY_MAYBE (showbase, showbaselen);     /* base */
104
105   DOPRNT_REPS_MAYBE ('0', zeros);                  /* zeros */
106
107   if (justify == DOPRNT_JUSTIFY_INTERNAL)          /* pad internal */
108     DOPRNT_REPS (p->fill, justlen);
109
110   /* if there's a showbase on the denominator, then print the numerator
111      separately so it can be inserted */
112   if (den_showbaselen != 0)
113     {
114       ASSERT (slash != NULL);
115       slashlen = slash+1 - s;
116       DOPRNT_MEMORY (s, slashlen);                 /* numerator and slash */
117       slen -= slashlen;
118       s += slashlen;
119       DOPRNT_MEMORY (showbase, den_showbaselen);
120     }
121
122   DOPRNT_MEMORY (s, slen);                         /* number, or denominator */
123
124   if (justify == DOPRNT_JUSTIFY_LEFT)              /* pad left */
125     DOPRNT_REPS (p->fill, justlen);
126
127  done:
128   return retval;
129
130  error:
131   retval = -1;
132   goto done;
133 }