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
__gmp_doprnt_integer(const struct doprnt_funs_t * funs,void * data,const struct doprnt_params_t * p,const char * s)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 }
134